C++20中的CTAD和指定初始化器

10

我已经在这个问题中表达了关于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上的示例。

扣除指南有点让人感到困惑。 - StoryTeller - Unslander Monica
1个回答

5

请参考这个答案作为开始。我们有相同的三位候选人:

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>;

模板参数始终来自于主类模板,因此我们从那里引入默认的模板参数。候选参数来自于初始化列表,而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>。也就是说,在为U填充默认模板参数后,变成了my_pair<float, float>
这就是为什么gcc会给你看到这种行为--它只是尚未实现用于聚合体的CTAD,并向您提供旧行为。

但是我最终得到了 my_pair<float, float>。根据你的回答(以及我的逻辑思考),我不应该这样。 - nnolte
2
因此,针对帖子中的问题。将“first”推断为“float”是编译器错误。 - StoryTeller - Unslander Monica
@kawillzocken 已添加更新,解释为什么你会得到 my_pair<float, float>。这不是编译器错误,而是编译器尚未实现此功能。 - Barry
GCC 9.1、Clang 9 和 VS 2019 16.1 都实现了 CTAD 和指定初始化器,但没有一个实现了聚合体的 CTAD。但只有 GCC 将第一个推断为浮点数。因此至少有一个编译器存在缺陷。而且 GCC 忽略指定符号的记录也很多。 - cpplearner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接