自动模板类型推导场景下函数模板参数列表初始化适配方案问询
编译失败的核心原因
你的写法无法编译是C++模板推导规则的硬性限制,和类模板推导指引的有效性无关:
- 无类名前缀的花括号初始化列表(
braced-init-list)本身没有确定的类型 - 模板参数推导阶段,除非函数形参是
std::initializer_list<U>或数组类型U[N],否则编译器不允许从braced-init-list推导模板参数 - 类模板实参推导(CTAD)仅在你显式写出类名时触发,纯
{"a",1}的写法下编译器根本不知道你要构造opt类型,自然不会调用你定义的推导指引
可行修改方案
方案1:扁平化键值对传参(无侵入,推荐)
不需要用户显式写opt或用{}包裹每组参数,直接按键1, 值1, 键2, 值2...的顺序传参即可,调用形式为function("a", 1, "b", 2., "c", 3u),实现如下:
#include <tuple> #include <utility> // 原有处理逻辑改名为function_impl template <typename... T> void function_impl(opt<T>&&... opts) { // 原有处理代码 } // 新增对外的扁平化参数接口 template <typename... Args> void function(Args&&... args) { static_assert(sizeof...(Args) % 2 == 0, "参数必须为 键,值 成对出现"); // 两两分组构造opt并转发给实现函数 []<std::size_t... I>(auto&& arg_tuple, std::index_sequence<I...>) { auto make_opt = [](auto&& name, auto&& val) { return opt(std::forward<decltype(name)>(name), std::forward<decltype(val)>(val)); }; function_impl(make_opt(std::get<2*I>(arg_tuple), std::get<2*I+1>(arg_tuple))...); }(std::forward_as_tuple(std::forward<Args>(args)...), std::make_index_sequence<sizeof...(Args)/2>{}); }
方案2:保留{}包裹每组参数的写法
如果一定要保留function({"a",1},{"b",2.},{"c",3u})的调用形式,可以通过宏实现,不需要修改原有业务逻辑:
// 递归宏给每个参数加opt前缀,支持最多10组参数,可按需扩展 #define OPT_WRAP_1(a) opt a #define OPT_WRAP_2(a, ...) opt a, OPT_WRAP_1(__VA_ARGS__) #define OPT_WRAP_3(a, ...) opt a, OPT_WRAP_2(__VA_ARGS__) #define OPT_WRAP_4(a, ...) opt a, OPT_WRAP_3(__VA_ARGS__) #define OPT_WRAP_5(a, ...) opt a, OPT_WRAP_4(__VA_ARGS__) #define OPT_WRAP_6(a, ...) opt a, OPT_WRAP_5(__VA_ARGS__) #define OPT_WRAP_7(a, ...) opt a, OPT_WRAP_6(__VA_ARGS__) #define OPT_WRAP_8(a, ...) opt a, OPT_WRAP_7(__VA_ARGS__) #define OPT_WRAP_9(a, ...) opt a, OPT_WRAP_8(__VA_ARGS__) #define OPT_WRAP_10(a, ...) opt a, OPT_WRAP_9(__VA_ARGS__) #define GET_OPT_WRAP(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,NAME,...) NAME #define OPT_WRAP(...) GET_OPT_WRAP(__VA_ARGS__, OPT_WRAP_10,OPT_WRAP_9,OPT_WRAP_8,OPT_WRAP_7,OPT_WRAP_6,OPT_WRAP_5,OPT_WRAP_4,OPT_WRAP_3,OPT_WRAP_2,OPT_WRAP_1)(__VA_ARGS__) // 把原来的函数名改名为function_impl,对外用宏包装 #define function(...) function_impl(OPT_WRAP(__VA_ARGS__)) template <typename... T> void function_impl(opt<T>&&... opts) { // 原有处理代码 }
内容的提问来源于stack exchange,提问作者SU3
相关产品推荐
相关产品推荐

