Question

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)?

Was it helpful?

Solution

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)       
{       
}

OTHER TIPS

The problem is that the declaration and the definition do not match.

The solution is that the declaration should contain the exact same signature, and the the 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 fine on VC2008.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top