简体   繁体   English

CAD中的CTAD和指定的初始化器20

[英]CTAD and designated initializers in C++20

I have already stated confusion about CTAD with designated initializers in this question , but i have another confusion with a very similar code snippet 在这个问题中 ,我已经说过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> );
}

It seems like the deduction guide causes the type of first to be deduced to float , even though i do not give an explicit .first in the designated initializer. 这似乎是扣除引导导致的类型first被推断为float ,即使我不给一个明确的.first在指定的初始化。 The deduction guide apparently only cares about the order in the initializer, no matter the keyword ( .second ). 无论关键字( .second )如何,演绎指南显然只关心初始化程序中的顺序。 Should the deduction guide be smart about this or should there be a "designated deduction guide"? 扣除指南应该明智还是应该有“指定扣除指南”?

See the example on https://godbolt.org/z/cm6Yi7 请参阅https://godbolt.org/z/cm6Yi7上的示例

See this answer as a starting point. 以此答案为出发点。 We have the same initial three candidates: 我们有三个相同的初始候选人:

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

And the aggregate deduction candidate is based on the actual initializer-list or designated-initializer-list we provide, not the actual underlying members of the aggregate. 并且总扣除候选者基于我们提供的实际初始化列表指定初始化列表 ,而不是聚合的实际基础成员。 Our designated-initializer-list is {.second = 20.f} so our aggregate deduction candidate becomes: 我们的指定初始化列表{.second = 20.f}因此我们的总扣除候选者变为:

// aggregate deduction candidate
template <class T=int, class U=float>
auto __f(U) -> my_pair<T, U>;

The template parameters always come from the primary class template, so we bring in the default template arguments from there. 模板参数总是来自主类模板,因此我们从那里引入默认模板参数。 The candidate arguments come from the initializer-list , and the type of second is U . 候选参数来自初始化列表second类型是U

The aggregate deduction candidate is the best candidate (only the aggregate deduction candidate and the deduction guide are viable, the aggregate deduction candidate is more specialized), so we end up with my_pair<int, float> . 总扣除候选人是最佳候选人(只有总扣除候选人和扣除指南是可行的,总扣除候选人更专业),所以我们最终得到my_pair<int, float>


Having finished CTAD, we now start over and effectively do 完成CTAD后,我们现在重新开始并有效地做到了

my_pair<int, float> x{.second = 20.f};

Which works, and leads to x.first being initialized from {} . 哪个有效,并导致x.first{}初始化。


CTAD for aggregates was only adopted very recently (at the Cologne meeting in July 2019, two months ago). 聚合物的CTAD最近才被采用(两个月前的2019年7月的科隆会议)。 Before that feature, this would still have been well-formed: 在此功能之前,这仍然是格式良好的:

my_pair{.second = 20.f};

Why? 为什么? We don't yet have the aggregate deduction candidate, but we still do have the deduction guide... which is viable. 我们还没有累计扣除候选人,但我们仍然有扣除指南......这可行的。 It gives us my_pair<float> . 它给了我们my_pair<float> Which is to say, my_pair<float, float> once you fill in the default template argument for U . 也就是说,一旦你填写U的默认模板参数, my_pair<float, float>

That's why gcc is giving you the behavior you see - it simply does not yet implement CTAD for aggregates, and is giving you the old behavior. 这就是为什么gcc会给你你看到的行为 - 它只是还没有为聚合实现CTAD,并且给你旧的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM