假设模板类的成员不应该被实例化,除非它们被使用。
然而,此示例似乎实例化了do_something
成员而enable_if
失败了(如果我们实例化它会是预期的 - 但我们没有实例化AFAIK)。
我错过了一些非常基本的东西吗?
#include <string>
#include <boost/utility.hpp>
struct some_policy {
typedef boost::integral_constant<bool, false> condition;
};
struct other_policy {
typedef boost::integral_constant<bool, true> condition;
};
template <typename policy>
class test {
void do_something(typename boost::enable_if<typename policy::condition>::type* = 0) {}
};
int main() {
test<other_policy> p1;
test<some_policy> p2;
}
答案 0 :(得分:8)
来自C ++ 11 14.7.1 / 1:
类模板特化的隐式实例化会导致隐式 实例化类成员函数
的声明,但不包括定义或默认参数
因此实例化了函数声明;失败,因为它取决于无效的类型。
(不幸的是,我没有任何历史版本的标准可供参考,但我想这个规则在C ++ 98中是类似的)
答案 1 :(得分:6)
Mike Seymour已经回答了为什么它不起作用,这里是如何解决它:
#include <string>
#include <boost/utility.hpp>
struct some_policy {
typedef boost::integral_constant<bool, false> condition;
};
struct other_policy {
typedef boost::integral_constant<bool, true> condition;
};
template <typename policy>
class test {
private:
template<typename P>
void do_something_impl(typename boost::enable_if<typename P::condition>::type* = 0) {}
public:
void do_something()
{
do_something_impl<policy>();
}
};
int main() {
test<other_policy> p1;
test<some_policy> p2;
}
快速经验法则:如果你想做SFINAE,你需要一个成员函数 template 。
答案 2 :(得分:4)
SFINAE仅在模板函数/方法上发生(这里,它是您的类,它是模板),
您可以使用C ++ 11(函数/方法的默认模板参数):
template <typename policy>
class test {
template <typename T = policy>
void do_something(typename boost::enable_if<typename T::condition>::type* = 0) {}
};
您也可以使用专业化,例如
template <bool> struct helper_do_something {};
template <> struct helper_do_something<true>
{
void do_something() { /* Your implementation */ }
};
template <typename policy>
class test : helper_do_something<T::condition::value>
{
// do_something is inherited (and it is present only when T::condition::value is true)
};