问题描述
我试过用 msvc 编译它,它编译得很好。另一方面,我未能用 g++ 和 clang++ 编译它。我得到的错误是 no type named ‘type’ in ‘struct std::enable_if<false,void>’
。我将如何解决此错误?
#include <type_traits>
template <bool v>
struct a {
template <typename T = typename std::enable_if<v>::type>
void function();
};
template struct a<false>;
template struct a<true>;
template<bool v>
template<typename T>
void a<v>::function() { }
int main() {
}
如果传递的 void function
模板为 bool
,我正在尝试使 true
可见。
解决方法
您没有正确使用 SFINAE,因为您传递给 bool
(即 enable_if
)的 v
不依赖于函数模板参数。
有选择地添加或删除类模板成员的规范方法是使用模板特化。例如:
template <bool v>
struct a {
void function();
};
template< >
struct a<false> {
};
现在,只有 a<true>
拥有 function
成员。如果您有许多共同成员应该出现在 a
中,而不管 v
,您可以将这些成员移动到基类并从中派生出两个特化:
struct a_common {
void common_function();
};
template <bool v>
struct a : public a_common {
void function();
};
template< >
struct a<false> : public a_common {
};
这也可以通过 SFINAE 来实现,但这需要一些技巧。如上所述,我们需要将function
做成一个模板,并且需要保证enable_if
中使用的条件依赖于它的模板参数。由于我们没有任何模板参数,我们需要添加一个虚拟参数:
template <bool v>
struct a {
template<
typename Dummy = void,typename = typename std::enable_if<
std::is_same< Dummy,Dummy >::value && v
>::type
>
void function();
};
这里,我们使用 is_same
trait 在计算 Dummy
的第一个模板参数时引入对 enable_if
模板参数的形式依赖。自然,is_same
的结果将是 true
,因此 v
有效地决定了 function
模板是否可以被实例化。