背景
考虑到我想在C ++ 03中实现以下人为构造:
(+)
template< typename T > // parameter list must contain T but may otherwise modified struct foo;
如果模板参数上的类型特征
dummy_trait<T>::value
T
中的foo
是true
,则foo
应该包含静态数据成员 类型为value
的名为T
的实例,它用整数文字表达式42
初始化;否则应该没有静态数据 名为value
的成员。
带有以下dummy_trait
(实际的虚拟特征可能有所不同):
template< typename T > struct dummy_trait { static const bool value = false; }; template<> struct dummy_trait<int> { static const bool value = true; };
问题
我自己的方法
使用助手
template< bool B, typename T = void >
struct enable_if {};
template< typename T >
struct enable_if<true, T> { typedef T type; };
例如使用部分类模板专门化:
// (A)
template< typename T, typename Enable = void >
struct foo {};
template< typename T >
struct foo<T, typename enable_if<dummy_trait<T>::value>::type > {
static const T value = 42;
};
例如利用SFINAE 在静态数据成员的声明中引入了条件错误(关于特征):
// (B)
template< typename T >
struct foo {
static const typename enable_if<
dummy_trait<T>::value, T >::type value = 42;
};
如果我没记错的话,上面的(A)
将允许使用foo
进行类型为T
的实例化,其中dummy_trait<T>::value
是false
(尽管不能是value
的{{1}}成员),而如果使用foo
,则根本不可能进行这样的实例化。
答案 0 :(得分:4)
除了以下两种方法(利用SFINAE)之外,是否还有其他(可能更合适)的替代方案来实现(+)?
与解决方案(A)并没有太大区别,但是...您可以通过继承获得结果
template <typename T>
struct foo : public bar<T>
{ };
bar
如下。
template <typename T, bool = dummy_trait<T>::value>
struct bar { };
template <typename T>
struct bar<T, true> { static const T value = 42; };
您还可以看到bar
是获得enable_if
的更简单方法(没有foo
)。
使用以下两种方法中的任何一种,是否有需要牢记的陷阱或方面?
我看到的唯一陷阱是您刚刚看到的陷阱:(B)方法不起作用,因为当foo
为dummy_trait<T>::value
时您无法定义false
。
我的意思是...(B)不是SFINAE,因为替换失败,在这种情况下,是一个错误。