nur*_*rbo 2 c++ templates variadic-templates c++11
我正在尝试创建一个可变参数模板函数,它将函数调用到连续的参数对.
所需的功能签名是:
template <typename ...Ts>
void apply(Ts &...args);
Run Code Online (Sandbox Code Playgroud)
当所谓apply(t1, t2, t3)的函数应该拨打电话的顺序func(t1, t2)和func(t2, t3),其中func是有特色的功能:
template <typename L, typename R>
void func(L &left, R &right);
Run Code Online (Sandbox Code Playgroud)
在我的上下文中,操作顺序并不真正相关.该函数具有以能够修改对象left和right,因此通过引用传递.我不能简单地通过基类指针使用多态访问,因为对象具有不同的类模板,共享类不能真正被取出.
是否有可能通过可变参数模板函数实现这样的调用序列?我见过的包扩展和折叠表达示例似乎都没有涵盖这种情况.或者我应该以不同的方式传递我的物体?
我的初始尝试,包括在下面(省略了一些细节),将所有模板参数打包到一个元组中,然后使用'const for-loop'来"循环"通过元组元素.但是,我很快意识到这种方法不起作用,因为const-for循环中的lambda会调用operator() const,因此无法修改传递的对象.
我使用的代码确实产生了所需的调用序列,但是对象没有被修改(set_something()不是const函数).我不得不求助于使用具有不同数量的模板参数的包装函数,并func手动调用.
template <std::size_t Begin, typename Callable, std::size_t... I>
constexpr void const_for_impl(Callable &&func, std::index_sequence<I...>) {
(func(std::integral_constant<std::size_t, Begin + I>{}), ...);
}
template <std::size_t Begin, std::size_t End, typename Callable>
constexpr void const_for(Callable &&func) {
const_for_impl<Begin>(std::forward<Callable>(func),
std::make_index_sequence<End - Begin>{});
};
template <typename... Ts>
void apply(Ts *... args) {
auto tuple = std::make_tuple(std::forward<Ts>(args)...);
const_for<0, sizeof...(args) - 1>(
[&](auto I) { func((std::get<I>(tuple)), (std::get<I + 1>(tuple))); });
};
template <typename L, typename R>
void func(L &l, R &r) {
// Validate with some type traits
static_assert(has_some_property<L>::value);
static_assert(has_another_property<R>::value);
// Get a shared pointer to something common
auto common = std::make_shared<typename something_common<L, R>::type>();
l.set_something(common);
r.set_something(common);
};
// Application scenario
int main() {
ComplexObjectA<SomeType, SomeParameter> a;
ComplexObjectB<AnotherType, AnotherParameter> b;
ComplexObjectC c;
apply(a, b, c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所以有什么问题?简单的折叠式模板(并记住模板模式匹配相反!)
template<typename T1, typename T2>
void apply(T1 &&t1, T2 &&t2) { func(t1, t2); }
template<typename T1, typename T2, typename... Ts>
void apply(T1 &&t1, T2 &&t2, Ts &&...ts) {
func(t1, t2);
return apply(t2, ts...);
}
Run Code Online (Sandbox Code Playgroud)
或者,更准确地说,它应该看起来像(感谢@MaxLanghof):
void apply(T1 &&t1, T2 &&t2) {
func(std::forward<T1>(t1), std::forward<T2>(t2));
}
template<typename T1, typename T2, typename... Ts>
void apply(T1 &&t1, T2 &&t2, Ts &&...ts) {
func(std::forward<T1>(t1), t2);
return apply(std::forward<T2>(t2), std::forward<TS>(ts)...);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
115 次 |
| 最近记录: |