Ant*_*ier 5 c++ templates c++17
基本上,我想要的是诸如multi_types之类的东西 std::initializer_list
template<typename ...As>
struct Foo {
Foo(As...){}
};
template<typename ...As>
void f(Foo<As...>) {}
int main() {
f(Foo{5, 3.f}); // 1) compile
f({}); // 2) compile
f({5, 3}); // 3) error
f({5, 3.8}); // 4) error
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我确实理解为什么第一个示例可以编译。但是,我不明白为什么第二个编译,而其他第二个却不编译。对我来说,如果第三个和第四个不编译,则第二个也不应该编译。有没有办法进行第三和第四编译?
但是,我不明白为什么第二个可以编译,而其他的则不能[编译]。
示例 3 和 4 无法编译,因为推导的模板参数与您期望的不同。
f({5, 3})当您向函数模板编写 call( ) 时template<typename ...As> void f(Foo<As...>),编译器需要推断出任何缺失的模板参数 ( ...As)。这些缺失的模板参数首先是通过将函数参数 ( {5, 3}) 与函数形参 ( Foo<As...>) 进行比较来推导出来的。如果函数参数是初始化列表 ( {5, 3}) [1],则函数参数( )会跳过模板参数推导Foo<As...>:
N4659 [临时扣除调用] 17.8.2.1(1):[...] 初始化列表参数导致该参数被视为非推导上下文 (17.8.2.5)。
N4659 [温度扣除类型] 17.8.2.5(5.6):[非推导上下文包括]函数参数,其关联参数是初始值设定项列表 (11.6.4) [...]
因为尾随模板参数 pack ( As...) 不是由任何函数参数推导的,所以它被推导为空:
N4659 [temp.arg.explicit] 17.8.1(3):未以其他方式推导的尾随模板参数包 (17.5.3) 将被推导为模板参数的空序列。
对于f({5, 3}),编译器推断模板参数为<>(空),因此被调用的特化为void f(Foo<>)。重要提示:无论初始值设定项列表中有什么内容,都会选择此专门化。这解释了编译器给出的诊断:
Clang:
错误:没有匹配的函数来调用“f”
注意:候选函数[with As = <>]不可行:无法将初始值设定项列表参数转换为“Foo <>”GCC:
错误:无法将“{5, 3}”从“”转换为“Foo<>”MSVC:
错误 C2664:“void f<>(Foo<>)”:无法将参数 1 从“初始化程序列表”转换为“Foo<>”
注意:没有构造函数可以采用源类型,或者构造函数重载解析不明确
在函数调用中,函数参数是使用函数参数的复制初始化来初始化的。以下语句使用与示例初始化参数相同的规则来初始化变量f:
Foo<> x = {}; // Example 2
Foo<> x = {5, 3}; // Example 3
Foo<> x = {5, 3.8}; // Example 4
Run Code Online (Sandbox Code Playgroud)
[1],简而言之,如果函数参数既不是std::initializer_list<T>也不是T[n]