如何使这个boost :: enable_if代码编译(SFINAE)?

时间:2012-08-19 17:30:46

标签: c++ boost sfinae enable-if

我很困惑为什么以下使用boost::enable_if的代码无法编译。它检查类型T是否具有成员函数hello,如果是这种情况则调用它:

#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);
}

我正在

no matching function for call to ‘doSomething(Foo&)

gcc 4.4.4

静态断言没问题,所以has_hello<Foo>::value确实是true。我使用boost::enable_if错了吗?

3 个答案:

答案 0 :(得分:4)

boost::enable_if的第一个参数必须是类型,其中包含名为bool的静态value常量。您需要的是enable_if_c模板(注意_c后缀),它采用非类型bool参数。

template<typename T>
void doSomething(T const& t,
                 typename boost::enable_if_c<has_hello<T>::value>::type* = 0
                 ) {
  return t.hello();
}

compiles and runs罚款。

还在Paragraph 2 in boost docs.

下解释

答案 1 :(得分:3)

下面

typename has_hello<T>::value

has_hello<T>::value不是类型名称。这很有价值。


不确定bost,但以下作品(gcc 4.7 std=c++0x):

template<typename T>
void doSomething(T const& t,
                 typename std::enable_if<has_hello<T>::value>::type* = 0
                 ) {
  return t.hello();
}

答案 2 :(得分:2)

到目前为止,我还没有使用enable_if,但可能

typename boost::enable_if<has_hello<T>>::type* = 0