提问人:dada_dave 提问时间:7/11/2023 最后编辑:Artyerdada_dave 更新时间:7/11/2023 访问量:56
将模板类的指定初始值设定项传递给模板函数
Passing designated initializers for a template class to a template function
问:
我的目标是创建一个如下所示的 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在最后一种情况下会失败?我能做些什么来让它成功吗?
答:
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> ab
function2(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 的那个是正确的,并且初始值设定项适合它。我已将您的答案标记为已接受,谢谢!
评论
function2(myAB2<int>{.a =1, .b =3});