c – 使用sfinae来检测可变参数模板的基类是否具有特定方法
发布时间:2020-12-16 10:02:07 所属栏目:百科 来源:网络整理
导读:我试图“迭代”一个可变参数派生类的所有基类,并调用一个名为“stream”的方法(如果它存在). 要检查方法是否存在,我使用sfinae,它可以工作(参见注释掉的代码).但是当我将它与可变参数模板“迭代”结合起来如果不起作用时,你的错误有点看起来像sfinae部分突然
我试图“迭代”一个可变参数派生类的所有基类,并调用一个名为“stream”的方法(如果它存在).
要检查方法是否存在,我使用sfinae,它可以工作(参见注释掉的代码).但是当我将它与可变参数模板“迭代”结合起来如果不起作用时,你的错误有点看起来像sfinae部分突然工作不像预期的那样,当在可变参数魔法里面. 帮助赞赏.我用的是gcc 5.3.0. #include <type_traits> #include <iostream> namespace detail{ template<class> struct sfinae_true : std::true_type{}; template<class T,class A0,class A1> static auto test_stream( int) -> sfinae_true<decltype( std::declval<T>().stream(std::declval<A0>(),std::declval<A1>()))>; template<class,class A1> static auto test_stream(long) -> std::false_type; } template<class T,class A1> struct has_stream : decltype(detail::test_stream<T,A0,A1>(0)){}; struct X{ void stream(int,bool){} }; struct A{ void stream(int,bool){} }; struct Y{}; template <typename ... T> class Z : public T ... { public: void ff() { std::initializer_list<bool> { ( has_stream<T,int,bool>() ? (T::stream(0,0),true) : false) ... }; } }; int main(){ Z<X,A> a; Z<X,A,Y> b; /* this works as expected. // this runs if (has_stream<X,bool>()) { std::cout << "has int,bool" << std::endl; } // and this doesn't if (has_stream<Y,long>()) { std::cout << "has int long" << std::endl; } */ a.ff(); // no error b.ff(); // error } $g++ --std=c++14 -O0 2.cpp 2.cpp: In instantiation of ‘void Z<T>::ff() [with T = X,Y]’: 2.cpp:41:10: required from here 2.cpp:22:52: error: ‘stream’ is not a member of ‘Y’ ( has_stream<T,true) : false) ... ^ 2.cpp:21:9: error: no matching function for call to ‘std::initializer_list<bool>::initializer_list(<brace-enclosed initializer list>)’ std::initializer_list<bool> { ^ 解决方法
使用由您的类型特征组成的标签调度:
void ff() { std::initializer_list<int> { (call<T>(has_stream<T,bool>{}),0)... }; } template <typename U> void call(std::true_type) { U::stream(0,0); } template <typename U> void call(std::false_type) {} 或使用表达式SFINAE: void ff() { std::initializer_list<int> { (call<T>(0),0)... }; } template <typename U> auto call(int) -> decltype(U::stream(0,void()) { U::stream(0,0); } template <typename U> void call(char) {} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |