我是编写模板元编程代码的新手(而不是仅仅阅读它)。所以我遇到了一些菜鸟问题。这篇名为“我的 SFINAE 发生了什么?”的非 SO 帖子很好地总结了其中之一。,我将 C++11 化为:
(注意:我给方法不同的名称只是为了帮助我在这个“思想实验”示例中进行错误诊断。请参阅@R.MartinhoFernandes关于为什么在实践中不会为非重载选择这种方法的注释。)
#include <type_traits>
using namespace std;
template <typename T>
struct Foo {
typename enable_if<is_pointer<T>::value, void>::type
valid_if_pointer(T) const { }
typename disable_if<is_pointer<T>::value, void>::type
valid_if_not_pointer(T) const { }
};
int main(int argc, char * argv[])
{
int someInt = 1020;
Foo<int*>().valid_if_pointer(&someInt);
Foo<int>().valid_if_not_pointer(304);
return 0;
}
@Alf 说 SFINAE 发生的事情是“它一开始就不存在”,并给出了编译的建议,但模板化的是函数而不是类。这在某些情况下可能是正确的,但并非全部。 (例如:我专门尝试编写一个容器,该容器可以容纳可能是或可能不是可复制构造的类型,我需要基于此打开和关闭方法。)
作为一种解决方法,我试了一下......这似乎工作正常。
#include <type_traits>
using namespace std;
template <typename T>
struct FooPointerBase {
void valid_if_pointer(T) const { }
};
template <typename T>
struct FooNonPointerBase {
void valid_if_not_pointer(T) const { }
};
template <typename T>
struct Foo : public conditional<
is_pointer<T>::value,
FooPointerBase<T>,
FooNonPointerBase<T> >::type {
};
int main(int argc, char * argv[])
{
int someInt = 1020;
#if DEMONSTRATE_ERROR_CASES
Foo<int*>().valid_if_not_pointer(&someInt);
Foo<int>().valid_if_pointer(304);
#else
Foo<int*>().valid_if_pointer(&someInt);
Foo<int>().valid_if_not_pointer(304);
#endif
return 0;
}
但是,如果这没有被破坏(是吗?),它肯定没有遵循一个很好的通用方法来基于嗅探特征的类型来打开和关闭模板类中的方法。有更好的解决方案吗?