【发布时间】:2016-03-23 15:03:46
【问题描述】:
我正在尝试“迭代”一个可变参数派生类的所有基类并调用一个名为“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 A0, class A1> static auto test_stream(long) -> std::false_type;
}
template<class T, class A0, 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, int, bool>()) {
std::cout << "has int, bool" << std::endl;
}
// and this doesn't
if (has_stream<Y, int, 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, A, Y]’:
2.cpp:41:10: required from here
2.cpp:22:52: error: ‘stream’ is not a member of ‘Y’
( has_stream<T,int,bool>() ? (T::stream(0, 0) , 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> {
^
【问题讨论】:
-
听起来像是concepts 的问题。
-
您能说得更具体些吗?根据我从文章中得到的信息 - c++14 中没有概念。我看不出我的代码不能在 c++14 中运行的任何原因(我不怪任何人,但我自己,不要误会我的意思)。
-
我并不是说你想要的行为在 C++14 领域是不可能的。我是说这似乎是一个很好的概念候选者,目前(以及可预见的未来)不可用。
-
我明白了。好吧,我希望我们能在更多的 C++ 标准版本中看到概念
标签: c++ c++14 variadic-templates sfinae