您可以重构或包装f
以返回一个新X
的而不是让它通过,因为这会在手中发挥包扩展并使函数真正简洁:
template<class T>
X fw(T const& t){ X x; f(x, t); return x; }
template<class... Args>
void h(Args... args){
X xs[] = { fw(args)... };
g(xs, sizeof...(Args));
}
活生生的例子。
如果您可以更改g
为只接受一个std::initializer_list
,它会变得更加简洁:
template<class... Args>
void h(Args... args){
g({f(args)...});
}
活生生的例子。或者(也许更好),您也可以只提供一个g
转发到真实的包装器g
:
void g(X const*, unsigned){}
void g(std::initializer_list<X> const& xs){ g(xs.begin(), xs.size()); }
template<class... Args>
void h(Args... args){
g({f(args)...});
}
活生生的例子。
编辑:另一个选择是使用临时数组:
template<class T>
using Alias = T;
template<class T>
T& as_lvalue(T&& v){ return v; }
template<class... Args>
void h(Args... args){
g(as_lvalue(Alias<X[]>{f(args)...}), sizeof...(Args));
}
活生生的例子。请注意,该as_lvalue
函数是危险的,数组仍然只存在到完整表达式的末尾(在这种情况下g
),所以使用它时要小心。Alias
是必需的,因为X[]{ ... }
由于语言语法,just 是不允许的。
如果所有这些都不可能,您将需要递归来访问args
包的所有元素。
#include <tuple>
template<unsigned> struct uint_{}; // compile-time integer for "iteration"
template<unsigned N, class Tuple>
void h_helper(X (&)[N], Tuple const&, uint_<N>){}
template<unsigned N, class Tuple, unsigned I = 0>
void h_helper(X (&xs)[N], Tuple const& args, uint_<I> = {}){
f(xs[I], std::get<I>(args));
h_helper(xs, args, uint_<I+1>());
}
template<typename... Args>
void h(Args... args)
{
static constexpr unsigned nargs = sizeof...(Args);
X xs[nargs];
h_helper(xs, std::tie(args...));
g(xs, nargs);
}
活生生的例子。
编辑:受 ecatmur 评论的启发,我使用了索引技巧使其仅与包扩展和原样工作f
,g
而不改变它们。
template<unsigned... Indices>
struct indices{
using next = indices<Indices..., sizeof...(Indices)>;
};
template<unsigned N>
struct build_indices{
using type = typename build_indices<N-1>::type::next;
};
template <>
struct build_indices<0>{
using type = indices<>;
};
template<unsigned N>
using IndicesFor = typename build_indices<N>::type;
template<unsigned N, unsigned... Is, class... Args>
void f_them_all(X (&xs)[N], indices<Is...>, Args... args){
int unused[] = {(f(xs[Is], args), 1)...};
(void)unused;
}
template<class... Args>
void h(Args... args){
static constexpr unsigned nargs = sizeof...(Args);
X xs[nargs];
f_them_all(xs, IndicesFor<nargs>(), args...);
g(xs, nargs);
}
活生生的例子。