c++ - 将可变参数分成两半
问题描述
我编写了一个便利函数,它获取一些参数,然后将它们发送到正确的函数:
void combine(int a, int b, double one, double two) {
funA(a,b);
funB(one, two);
}
现在我想再做一次,但我的combine
函数和funA
-funB
对都使用可变模板参数:
//somewhere earlier in the code
template<class U, class T> funA(U par1, T par2) {...}
template<class X, class Y> funB(X par1, Y par2) {...}
template<class ...ParamA, class ...ParamB>
void combine(ParamA...packA, ParamB...packB) {
funA(packA...);
funB(packB...);
}
这当然行不通,因为我需要一些方法将参数列表分成两半。但更有趣的是,当我尝试通过调用来编译上述代码时,
combine(10, 'a', 12.0, true)
我得到了这个错误:
In instantiation of ‘void combine(ParamA ..., ParamB ...) [with ParamA = {}; ParamB = {int, char, double, bool}]’:
...
error: no matching function for call to ‘funA()’
....
error: no matching function for call to ‘funB(int&, char&, double&, bool&)’
这表明ParamB
“吃”了所有参数列表。
所以,我的问题是:有没有办法将带有变量模板列表的函数的参数列表分成两半?. 如果没有,我还能如何编写我的combine
函数?
解决方案
#include <tuple>
#include <utility>
#include <iostream>
#include <memory>
//somewhere earlier in the code
template<class U, class T> void funA(U par1, T par2) {
std::cout<<par1 <<' '<< par2 <<'\n';
}
// Use move-only type to check forwarding
template<class X> void funB(X par1, std::unique_ptr<int> par2) {
std::cout<<par1 <<' '<< *par2 <<'\n';
}
// Call fnc with a subset of arguments, more general than we need for the partitioning.
template<typename Fnc,std::size_t...Is, typename...Args>
auto call_sub(Fnc fnc, std::index_sequence<Is...>, Args&&...args){
auto tup = std::forward_as_tuple(std::forward<Args>(args)...);
// Extract relevant indices.
return fnc(std::get<Is>(std::move(tup))...);
}
// Shift index sequences
template< std::size_t shift_amount,std::size_t...Is>
constexpr auto shift_sequence( std::index_sequence<Is...>){
return std::index_sequence<shift_amount +Is...>{};
}
template<class ...Params>
void combine(Params&&...pack) {
static_assert(sizeof...(pack) % 2 == 0);
constexpr std::size_t half = sizeof...(pack) /2;
constexpr std::make_index_sequence<half> first_half;
constexpr auto second_half = shift_sequence<half>(first_half);
// Lambda must be used because funA nor funB are not functions, they are templates which cannot be passed around.
call_sub([](auto&&...args){return funA(std::forward<decltype(args)>(args)...);},
first_half, std::forward<Params>(pack)...);
call_sub([](auto&&...args){return funB(std::forward<decltype(args)>(args)...);},
second_half, std::forward<Params>(pack)...);
}
int main (int argc, char *argv[])
{
combine(1,2,3,std::make_unique<int>(10));
}
输出:
1 2
3 10
推荐阅读
- python - 这是列表开始的限制吗?
- python - Python 的 len() 内置 O(1) 时间复杂度背后的秘密是什么
- scala - 多次使用prepared statement,提示Cassandra Querying Reducing Performance
- java - Spring 5 LDAP 身份验证和 JWT 令牌作为响应
- firefox-addon - 是否可以在 Firefox Quantum 中查看上传百分比
- java - Java 的 BouncyCastle 并不总是验证 OpenSSL ECDSA 签名
- function - filesystemwatcher事件函数powershell中的访问函数
- node.js - 运行 MEAN 应用程序时出现“无默认引擎”错误
- javascript - 将 Google NodeJS 语音转文本与来自客户端麦克风的音频一起使用
- database - 给定查询的关系代数表达式