Forward declaration of function that uses enable_if: ambiguous call

I have a problem declaring a function that uses boost::enable_if : the following code fragment gives me a compiler error:

 // Declaration template <typename T> void foo(T t); // Definition template <typename T> typename boost::enable_if<boost::is_same<T, int> >::type foo(T t) { } int main() { foo(12); return 0; } 

When compiling, I get the "ambiguous call foo" error. According to the definition of enable_if , typedef "type" matches void , when the condition is true, as far as I can see, two foo signatures match. Why does the compiler think that they are different, and is there a proper way to forward the declaration to foo (preferably without repeating the enable_if part)?

+4
source share
2 answers

This is not only a problem with enable_if. You get the same error in Visual Studio and gcc with the following code:

 struct TypeVoid { typedef void type; }; template<typename T> void f(); template<typename T> typename T::type f() { } int main() { f<TypeVoid>(); return 0; } 

I think the main problem is that the return type (before instantiation) is part of the signature of the template function. There is more details here .

As for your code, if the declaration is relevant to the definition, you should match both:

 // Declaration template <typename T> typename boost::enable_if<boost::is_same<T, int> >::type foo(T t); // Definition template <typename T> typename boost::enable_if<boost::is_same<T, int> >::type foo(T t) { } 

If the declaration refers to another function, the compiler can never choose the right one for ints, because both of them are valid. However, you can disable the first for int with disable_if:

 // Other function declaration template <typename T> typename boost::disable_if<boost::is_same<T, int> >::type foo(T t); // Defition template <typename T> typename boost::enable_if<boost::is_same<T, int> >::type foo(T t) { } 
+3
source

The problem is that the declaration and definition are not consistent.

The solution is that the declaration must contain the same signature and enable_if bit.

 #include <boost/type_traits/is_same.hpp> #include <boost/utility/enable_if.hpp> // Declaration template <typename T> typename boost::enable_if<boost::is_same<T, int> >::type foo(T t); // Definition template <typename T> typename boost::enable_if<boost::is_same<T, int> >::type foo(T t) { } int main() { foo(12); return 0; } 

This compiles on the VC2008.

+1
source

All Articles