将模板类的指定初始值设定项传递给模板函数

Passing designated initializers for a template class to a template function

提问人:dada_dave 提问时间:7/11/2023 最后编辑:Artyerdada_dave 更新时间:7/11/2023 访问量:56

问:

我的目标是创建一个如下所示的 API 接口:

struct myAB{ int a,b; };

void function(myAB ab) {}

...

function({.a = 1, .b = 3});

以上效果很好。但是,如果我希望结构 AB 具有模板化类型,CTAD 就会失败。

template <class B>
struct myAB2{ int a; B b; };
template<typename B> myAB2(int, B) ->  myAB2<B>; 

template<typename B>
void function2(myAB2<B> ab) {}

...

myAB2 ab = {.a = 1, .b = 3}; //works just fine with CTAD
function2(ab); //fine as expected
function2(myAB2{.a = 1, .b = 3}); //works just fine with CTAD
function2({.a = 1, .b = 3}); //fails to compile, can't deduce type 'B'

为什么CTAD在最后一种情况下会失败?我能做些什么来让它成功吗?

https://godbolt.org/z/7Es4Y11Yf

C++ 函数参数 模板类 CTAD

评论

0赞 Paul Sanders 7/11/2023
您问题中的代码与 godbolt 链接中的代码不匹配。
0赞 Paul Sanders 7/11/2023
看起来您无法从初始值设定项列表中推断出模板参数(这似乎是合理的)。 可能是你能做的最好的。function2(myAB2<int>{.a =1, .b =3});
0赞 dada_dave 7/11/2023
啊,对不起,修复了我认为的主要差异(与我上面最初的想法不同,我将两个示例放入一个 Godbolt 文件中,我想让事情尽可能简单,所以我将所有内容重命名为 2)
0赞 dada_dave 7/11/2023
函数2(myAB2{.a = 1, .b = 3});有效,但我仍然觉得奇怪的是,将结构化绑定(本质上是初始值设定项列表)传递给变量可以工作,但将其传递给相同类型的函数参数却没有
0赞 n. m. could be an AI 7/11/2023
“我能做些什么来让它成功吗?”编写并提交一个出色的提案,将命名函数参数添加到下一个 C++ 标准中。不过没有保证。

答:

3赞 Artyer 7/11/2023 #1

braced-init-list(包括包含指定初始值设定项的列表)没有类型。你只能从中推导出或数组类型,这在这里没有发生。std::initializer_list

由于不是表达式,也没有类型,因此无法从中推导出任何内容,因此无法调用该函数。{.a = 1, .b = 3}function2({.a = 1, .b = 3})B

function2<int>({.a = 1, .b = 3})会起作用(因为可以使用指定的初始值设定项进行初始化,因此无需再进行推导)。
所以会(因为这确实 CTAD 得到一个 类型的 prvalue ,可以从中推导出来)。
myAB2<int> abfunction2(myAB2{.a = 1, .b = 3})myAB2<int>B = int

评论

0赞 dada_dave 7/11/2023
有效,因为它是一个表达式?myAB2 ab = {.a = 1, .b = 3};
1赞 Artyer 7/11/2023
@dada_dave CTAD(是初始值设定项,而不是表达式)与 .{.a=1, .b=3}auto ab = myAB2{.a = 1, .b = 3}
0赞 dada_dave 7/11/2023
啊,所以传递给不算作初始值设定项,尽管对于 myAB2,即使它被传递到的参数是 myAB2 类型?{.a = 1, .b =3}function2
1赞 Artyer 7/11/2023
@dada_dave它将是一个初始值设定项,但是由于无法推断,因此没有要调用的函数重载B
0赞 dada_dave 7/11/2023
明白了,所以因为在选择要调用的函数之前无法推断出 B,所以如果没有额外的信息,它无法知道哪个潜在函数 2 是正确的,无论是 <int> 还是 myAB2。因此,它不一定知道带有 myAB2 的那个是正确的,并且初始值设定项适合它。我已将您的答案标记为已接受,谢谢!