让我们使用以下代码创建一个元组树和一个n-ary运算符来聚合特定级别的值:
#include <tuple>
template<class O, class... I>
struct Compose
{
using ITuple = std::tuple<I...>;
Compose(O&& o, I&&... i) :
o(std::forward<O>(o)),
i(std::forward<I>(i)...)
{ }
float operator ()(float x) const
{ /* return o(i1(x), i2(x), i3(x), ... ); */ }
template<unsigned H1, unsigned H2, unsigned... Ts>
decltype(auto) getI()
{ return std::get<H1>(i).getI<H2, Ts...>(); }
template<unsigned H>
decltype(auto) getI()
{ return std::get<H>(i); }
O o;
ITuple i;
};
template<class O, class... I>
Compose<O, I...>
make_compose(O&& o, I&&... i)
{ return Compose<O, I...>(std::forward<O>(o), std::forward<I>(i)...); }
struct Foo {
Foo(float param) : p(param) { }
float operator()(float v) const
{ return p * v; }
float p;
};
int main()
{
auto out = [](float x, float y) { return x + y; };
auto c1 = make_compose(out, make_compose(out, Foo(2), Foo(3)), Foo(4));
auto test1 = c1.getI<0, 1>();
test1(1); // will return 3
return 0;
}
我正在使用-std = C ++ 14进行编译,当我使用GCC 6.4时,它编译得很好。但是对于clang ++ 3.9,它失败并出现错误:
错误:表达式包含未展开的参数包&#39;
Ts
&#39;
{ return std::get<H1>(i).getI<H2, Ts...>(); }
有谁知道真正的问题在哪里,因为它看起来像是可变参数包的明显扩展。方法getI()
通过该树级别的索引返回树中的元素。
我找到了方法getI<>()
的解决方法,它将元组元素传递给帮助函数doGetI()
在clang中工作,但看起来很乱:
template<unsigned... Ts>
decltype(auto) getI()
{ return doGetI<Compose2, Ts...>(*this); }
template<class T, unsigned H1, unsigned H2, unsigned... Ts>
decltype(auto) doGetI(T& t)
{ return doGetI<std::tuple_element_t<H1, typename T::ITuple>, H2, Ts...>(std::get<H1>(t._i)); }
template<class T, unsigned H>
decltype(auto) doGetI(T& t)
{ return std::get<H>(t._i); }