I have some trouble forward declaring a function that uses boost::enable_if
: the following piece of code 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 an "ambiguous call to foo" error. According to the definition of enable_if
, the 'type' typedef corresponds to void
when the condition is true, so as far as I can see, the two signatures of foo
match. Why does the compiler think they are different, and is there a correct way to forward declare foo
(preferably without repeating the enable_if
part)?
This is not only a problem with enable_if. You get the same error on 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 a template function. There is more information here.
Regarding your code, if the declaration refers 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 a different function, the compiler would never be able to choose the correct one for ints, because they both are valid. However, you can disable the first one for ints using 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)
{
}