c – 为什么SFINAE在这种情况下对我不正确以及如何解决?
发布时间:2020-12-16 10:07:55 所属栏目:百科 来源:网络整理
导读:我试图在struct A中留下一个函数foo(打印0),如果它的参数有模板方法isA void和另一个(打印1),如果没有.这段代码(简化为下面的最小例子)编译(尝试使用 gcc 6.1.0和clang-3.9.0以及显式–std = c 14选项)并运行. 但它打印1,但是,我确信,它将打印0.我想知道我错
我试图在struct A中留下一个函数foo(打印0),如果它的参数有模板方法isA< void>和另一个(打印1),如果没有.这段代码(简化为下面的最小例子)编译(尝试使用
gcc 6.1.0和clang-3.9.0以及显式–std = c 14选项)并运行.
但它打印1,但是,我确信,它将打印0.我想知道我错在哪里,但真正的问题是:如何使这项工作正确? 请只使用C 14解决方案. #include <type_traits> #include <iostream> #include <utility> using std::enable_if; using std::declval; using std::true_type; using std::false_type; using std::cout; template<int M> struct ObjectX { template<typename C> bool isA() { return false; } }; struct XX : ObjectX<23456> { int af; }; template <typename ObjType> using has_dep = decltype(declval<ObjType>().template isA<void>()); template <typename,typename = void> struct has_isa : public false_type {}; template <typename ObjType> struct has_isa<ObjType,has_dep<ObjType> > : public true_type {}; template<typename ObjType> struct A { template<typename T = void> typename enable_if<has_isa<ObjType>::value,T>::type foo() { cout << "called foo #0" << "n"; } template<typename T = void> typename enable_if<!has_isa<ObjType>::value,T>::type foo() { cout << "called foo #1" << "n"; } }; int main() { A<XX> axx; // XX().template isA<void>(); -- to check,that we can call it and it exists axx.foo(); return 0; } 解决方法
这个程序有两个问题.
首先,has_dep< XX>是布尔.当我们尝试has_dep< XX>时,添加默认模板参数意味着这实际上是has_dep< XX,void>.但专业化是has_dep< XX,bool> – 这与我们实际查找的内容不符.布尔与虚空不符.这就是为什么has_dep< XX>是false_type.对此的解决方案是 其次,这是不对的: template<typename T = void> typename enable_if<has_isa<ObjType>::value,T>::type SFINAE仅发生在替换的直接上下文中,并且类模板参数不在函数模板替换的直接上下文中.这里正确的模式是: template <typename T = ObjType> // default to class template parameter enable_if_t<has_isa<T>> // use the function template parameter to SFINAE foo() { ... } 进行这两个修复,程序按预期工作. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |