kaw*_*ken 7 c++ designated-initializer c++20 ctad
我已经在这个问题中对使用指定的初始化程序的CTAD感到困惑,但是我对另一个非常相似的代码段也感到困惑
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{.second = 20.f};
    static_assert( std::is_same_v<decltype(x.first), int> ); //FAILS <- its deduced to float
    static_assert( std::is_same_v<decltype(x.second), float> );
}
即使我没有在指定的初始值设定项中给出显式信息,推论指南似乎也将推导类型first推导为。无论关键字(),推论指南显然只关心初始化程序中的顺序。演绎指南应该明智吗?还是应该有一个“指定演绎指南”?float.first.second
请参阅https://godbolt.org/z/cm6Yi7上的示例
见这个答案为出发点。我们有相同的初始三个候选人:
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...>;
并且聚合推演候选基于我们提供的实际初始化列表或指定初始化列表,而不是聚合的实际底层成员。我们的指定初始值设定项列表是{.second = 20.f}这样我们的聚合扣除候选者变成:
// aggregate deduction candidate
template <class T=int, class U=float>
auto __f(U) -> my_pair<T, U>;
模板参数总是来自主类模板,所以我们从那里引入默认模板参数。候选参数来自initializer-list,类型second是U。
聚合推演候选是最好的候选(只有聚合推演候选和推演指南是可行的,聚合推演候选更专业),所以我们最终得到my_pair<int, float>。
完成 CTAD 后,我们现在重新开始并有效地做
my_pair<int, float> x{.second = 20.f};
哪个有效,并导致x.first从{}.
用于聚合的 CTAD 直到最近才被采用(两个月前,在 2019 年 7 月的科隆会议上)。在该功能之前,这仍然是格式良好的:
my_pair{.second = 20.f};
为什么?我们还没有汇总扣除候选人,但我们仍然有扣除指南......这是可行的。它给了我们my_pair<float>。也就是说,my_pair<float, float>一旦你为U.
这就是为什么 gcc 给你你看到的行为 - 它只是还没有为聚合实现 CTAD,而是给你旧的行为。
| 归档时间: | 
 | 
| 查看次数: | 136 次 | 
| 最近记录: |