具有模板化类型的 C++20 指定初始值设定项
C++20 designated initializers with templated types
指定初始化器 (C++20) 应该如何与 CTAD 一起工作?
此代码在 gcc9.2 中运行良好,但在 clang8 中运行失败
template <typename int_t=int, typename float_t=float>
struct my_pair {
int_t first;
float_t second;
};
template<typename ... ts>
my_pair(ts...) -> my_pair<ts...>;
int main() {
my_pair x{.first = 20, .second = 20.f};
static_assert( std::is_same_v<decltype(x.first), int> );
static_assert( std::is_same_v<decltype(x.second), float> );
}
这应该有效吗?
是的,这应该是有效的。
CTAD 的工作方式是我们对一组合成的构造函数执行重载解析,以确定 class 模板参数是什么。从 C++17 开始,合成的构造函数集仅基于主模板的构造函数和推导指南(我正在更改模板参数名称,因为我发现它们非常混乱):
template <class T=int, class U=float>
struct my_pair {
T first;
U second;
};
// default constructor
template <class T=int, class U=float>
auto __f() -> my_pair<T, U>;
// copy candidate
template <class T=int, class U=float>
auto __f(my_pair<T, U>) -> my_pair<T, U>;
// deduction guide
template <class... T>
auto __f(T...) -> my_pair<T...>;
C++20 添加了一个新的聚合推导候选。对于 initializer-list 或 designated-initializer-list 的每个元素,我们选择聚合的相应元素并将其类型用作新候选人。对于
my_pair x{.first = 20, .second = 20.f};
first
的类型是T
,second
的类型是U
,因此:
// aggregate deduction candidate
template <class T=int, class U=float>
auto __f(T, U) -> my_pair<T, U>;
现在,我将这四个候选项写为函数(因为我发现将它们视为函数更容易),但措辞将它们定义为假设的 class 类型的构造函数。因此,当我们使用 {.first = 20, .second = 20.f}
执行重载解析时,如果你眯着眼睛看它是可行的。
最后一个候选是最好的候选(只有聚合推导候选和推导指南可行,聚合推导候选更专业),所以我们最终得到my_pair<int, float>
。
完成 CTAD 后,我们现在重新开始并有效地做
my_pair<int, float> x{.first = 20, .second = 20.f};
这当然有效。
指定初始化器 (C++20) 应该如何与 CTAD 一起工作?
此代码在 gcc9.2 中运行良好,但在 clang8 中运行失败
template <typename int_t=int, typename float_t=float>
struct my_pair {
int_t first;
float_t second;
};
template<typename ... ts>
my_pair(ts...) -> my_pair<ts...>;
int main() {
my_pair x{.first = 20, .second = 20.f};
static_assert( std::is_same_v<decltype(x.first), int> );
static_assert( std::is_same_v<decltype(x.second), float> );
}
这应该有效吗?
是的,这应该是有效的。
CTAD 的工作方式是我们对一组合成的构造函数执行重载解析,以确定 class 模板参数是什么。从 C++17 开始,合成的构造函数集仅基于主模板的构造函数和推导指南(我正在更改模板参数名称,因为我发现它们非常混乱):
template <class T=int, class U=float>
struct my_pair {
T first;
U second;
};
// default constructor
template <class T=int, class U=float>
auto __f() -> my_pair<T, U>;
// copy candidate
template <class T=int, class U=float>
auto __f(my_pair<T, U>) -> my_pair<T, U>;
// deduction guide
template <class... T>
auto __f(T...) -> my_pair<T...>;
C++20 添加了一个新的聚合推导候选。对于 initializer-list 或 designated-initializer-list 的每个元素,我们选择聚合的相应元素并将其类型用作新候选人。对于
my_pair x{.first = 20, .second = 20.f};
first
的类型是T
,second
的类型是U
,因此:
// aggregate deduction candidate
template <class T=int, class U=float>
auto __f(T, U) -> my_pair<T, U>;
现在,我将这四个候选项写为函数(因为我发现将它们视为函数更容易),但措辞将它们定义为假设的 class 类型的构造函数。因此,当我们使用 {.first = 20, .second = 20.f}
执行重载解析时,如果你眯着眼睛看它是可行的。
最后一个候选是最好的候选(只有聚合推导候选和推导指南可行,聚合推导候选更专业),所以我们最终得到my_pair<int, float>
。
完成 CTAD 后,我们现在重新开始并有效地做
my_pair<int, float> x{.first = 20, .second = 20.f};
这当然有效。