使用enable_if作为模板参数的模板类方法定义

时间:2012-03-11 23:27:06

标签: c++ templates

我之前问过this question a solution出现在哪里。就问题而言,解决方案很棒,但现在我对如何定义类的外部方法感到困惑,即我想在.inl中定义方法文件。在这种情况下,语法是什么?

为了清楚起见,对于模板类,方法定义将是:

template <typename T>
struct Foo
{
  Foo();
};

// C-tor definition
template <typename T>
Foo<T>::Foo()
{
}

如何使用enable_if作为参数之一定义模板类的方法?

template <typename Policy, enable_if< is_base<BasePolicy, Policy>::value >::type >
struct Foo
{
  Foo();
};

// C-tor definition -- ???

2 个答案:

答案 0 :(得分:14)

从它的外观来看,你想要做的事情就是这样:

template <typename Policy,
          typename = typename std::enable_if<std::is_base_of<BasePolicy, Policy>::value>::type >
struct Foo;

template <typename Policy>
struct Foo<Policy> {
    Foo();
};

template <typename Policy>
Foo<Policy>::Foo() {
}

这偷偷地利用了几个地方的默认参数:不要混淆,隐含的void坐在几个地方。

答案 1 :(得分:8)

以下是SFINAE如何实际使用部分专业化:

template<typename T, typename Sfinae = void>
struct Foo {
    /* catch-all primary template */
    /* or e.g. leave undefined if you don't need it */
};

template<typename T>
struct Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type> {
    /* matches types derived from BasePolicy */
    Foo();
};

然后可以通过以下方式笨拙地介绍该构造函数的定义:

template<typename T>
Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type>::Foo()
{
    /* Phew, we're there */
}

如果你的编译器支持模板别名(它是一个C ++ 11特性),那么你可以减少很多冗长:

template<typename T>
using EnableIfPolicy = typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type;

// Somewhat nicer:

template<typename T>
struct Foo<T, EnableIfPolicy<T>> {
    Foo();
};

template<typename T>
Foo<T, EnableIfPolicy<T>>::Foo() {}

注意:您的原始答案提到了Boost的实用程序,例如boost::enable_if_cboost::is_base_of。如果您使用的是std::enable_ifstd::is_base_of(来自C ++ 11),那么使用情况就像

typename boost::enable_if<boost::is_case_of<BasePolicy, T> >::type

其优点是可以摆脱一个::value