template <int I> struct int_ {};
template < typename ... Pack >
struct thingy
{
void call()
{
f(???);
}
};
实例化时,最终应该是:
struct thingy<int,char,double>
{
void call()
{
f(int, int_<1>(), char, int_<2>(), double, int_<3>());
}
}
您的想法,可以做到吗?怎么样?
我唯一能想到的就是使用N个不同的参数来实现重载:
template < typename T0 > struct thingy<T0> { ... };
template < typename T0, typename T1 > struct thingy<T0,T1> { ... };
etc...
每个都有一个调用实现。
答案 0 :(得分:4)
可以做到吗
是的,当然。
怎么样?
分几个步骤。
让我们从整数范围开始。
template <size_t...>
struct IntegralPack {};
template <size_t A, size_t... N>
IntegralPack<N..., A> push_back(IntegralPack<N...>);
template <size_t A, size_t... N>
IntegralPack<A, N...> push_front(IntegralPack<N...>);
template <size_t L, size_t H>
struct IntegralRangeImpl {
typedef typename IntegralRangeImpl<L+1, H>::type Base;
typedef decltype(push_front<L>((Base()))) type;
};
template <size_t X>
struct IntegralRangeImpl<X, X> {
typedef IntegralPack<> type;
};
template <size_t L, size_t H>
struct IntegralRange {
static_assert(L <= H, "Incorrect range");
typedef typename IntegralRangeImpl<L, H>::type type;
};
转换步骤很简单(谢天谢地):
template <typename...>
struct TypePack {};
template <size_t... N>
TypePack<int_<N>...> to_int(IntegralPack<N...>);
所以接下来的困难是合并。
template <typename... As, typename... Bs>
TypePack<As..., Bs...> cat(TypePack<As...>, TypePack<Bs...>);
template <typename, typename> struct Interleaver;
template <>
struct Interleaver<TypePack<>, TypePack<>> {
typedef TypePack<> type;
};
template <typename A0, typename B0, typename... As, typename... Bs>
struct Interleaver<TypePack<A0, As...>, TypePack<B0, Bs...>> {
typedef typename Interleaver<TypePack<As...>, TypePack<Bs...>>::type Base;
typedef decltype(cat(TypePack<A0, B0>{}, Base{})) type;
};
完全放弃:
template <typename... Pack>
struct thingy {
typedef typename IntegralRange<1, sizeof...(Pack) + 1>::type Indexes;
typedef decltype(to_int(Indexes{})) Ints;
typedef typename Interleaver<TypePack<Pack...>, Ints>::type Types;
void call() { this->callImpl(Types{}); }
template <typename... Ts>
void callImpl(TypePack<Ts...>) {
f(Ts{}...);
}
};
Tadaam!
答案 1 :(得分:0)
所以我采用它的方式对我实际做的事情稍微具体一点。结果发现我认为除了帮助我之外的一些信息。我认为虽然可以在任何情况下使用类似的技术。
一方面......在我的案例中“thingy&lt;&gt;”实际上有值,并传递给调用函数。这实际上有很大帮助。
此外,由于对象是将thing中的东西转换成另一个奇怪的东西,并且传入的int是索引第一个东西......当我执行时,int最终都是1递归。因此,虽然我所追求的是(简化为删除第二元组):
f(get(my_thingy, idx<1>), get(my_thingy, idx<2>), ...)
事实证明递归摆脱了idx&lt; 2&gt; ... idx:
template < typename Fun, typename H, typename ... T, typename ... Args >
auto call(Fun f, thingy<H,T...> const& t, Args&& ... args)
-> decltype(call(f,static_cast<thingy<T...>const&>(t), get(t,idx<1>), std::forward<Args>(args)...)
{
return call(f, static_cast<thingy<T...>const&>(t), get(t, idx<1>), args...);
}
template < typename Fun, typename ... Args >
auto call(Fun f, thingy<> const&, Args&& ... args)
-> decltype(f(std::forward<Args>(args)...))
{
return f(std::forward<Args>(args)...);
}
我无法完全测试东西,因为get
函数在使用const&amp; ...有点惹我生气时由于某种原因失败了。我相信这可以解决这个问题。
如果idx的参数不总是1,我认为可以以类似的方式转发。