I'm puzzled why the following code that uses boost::enable_if
doesn't compile. It checks if type T
has a member function hello
and calls it if that's the case:
#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <boost/static_assert.hpp>
// Has_hello<T>::value is true if T has a hello function.
template<typename T>
struct has_hello {
typedef char yes[1];
typedef char no [2];
template <typename U> struct type_check;
template <typename U> static yes &chk(type_check<char[sizeof(&U::hello)]> *);
template <typename > static no &chk(...);
static const bool value = sizeof(chk<T>(0)) == sizeof(yes);
};
template<typename T>
void doSomething(T const& t,
typename boost::enable_if<typename has_hello<T>::value>::type* = 0
) {
return t.hello();
}
// Would need another doSomething` for types that don't have hello().
struct Foo {
void hello() const {
std::cout << "hello" << std::endl;
}
};
// This check is ok:
BOOST_STATIC_ASSERT(has_hello<Foo>::value);
int main() {
Foo foo;
doSomething<Foo>(foo);
}
I'm getting
no matching function for call to ‘doSomething(Foo&)
with gcc 4.4.4
.
The static assert is ok, so has_hello<Foo>::value
is indeed true
. Am I using boost::enable_if
wrong?
First parameter for boost::enable_if
must be a type that contains a static bool
constant named value
. What you need is enable_if_c
template (note _c suffix) that takes a non-type bool
parameter.
template<typename T>
void doSomething(T const& t,
typename boost::enable_if_c<has_hello<T>::value>::type* = 0
) {
return t.hello();
}
This compiles and runs fine.
Also explained under Paragraph 2 in boost docs.