gpt4 book ai didi

c++ - std::common_type 的特化 - 误解、错误、两者兼而有之?

转载 作者:搜寻专家 更新时间:2023-10-31 02:01:52 26 4
gpt4 key购买 nike

用 C++17 标记,因为这是我引用的规范版本。

这是 IMO,标准的相关部分,第 23.15.7.6 节 [meta.trans.other]。

template <class... T> struct common_type;

Unless this trait is specialized (as specified in Note B, below), the member type shall be defined or omitted as specified in Note A, below. If it is omitted, there shall be no member type. Each type in the parameter pack T shall be complete, cv void, or an array of unknown bound.

附注A...

3. Note A: For the common_type trait applied to a parameter pack T of types, the member type shall be either defined or not present as follows:

(3.1) — If sizeof...(T) is zero, there shall be no member type.

(3.2) — If sizeof...(T) is one, let T0 denote the sole type constituting the pack T. The member typedef-name type shall denote the same type, if any, as common_type_t<T0, T0>; otherwise there shall be no member type.

(3.3) — If sizeof...(T) is two, let the first and second types constituting T be denoted by T1 and T2, respectively, and let D1 and D2 denote the same types as decay_t<T1> and decay_t<T2>, respectively.

(3.3.1) — If is_same_v<T1, D1> is false or is_same_v<T2, D2> is false, let C denote the same type, if any, as common_type_t<D1, D2>.

(3.3.2) — Otherwise, let C denote the same type, if any, as decay_t<decltype(false ? declval<D1>() : declval<D2>())> [ Note: This will not apply if there is a specialization common_type<D1, D2>. — end note ]

In either case, the member typedef-name type shall denote the same type, if any, as C. Otherwise, there shall be no member type.

(3.4) — If sizeof...(T) is greater than two, let T1, T2, and R, respectively, denote the first, second, and (pack of) remaining types constituting T. Let C denote the same type, if any, as common_type_t<T1, T2>. If there is such a type C, the member typedef-name type shall denote the same type, if any, as common_type_t<C, R...>. Otherwise, there shall be no member type.

和注释 B...

4. Note B: Notwithstanding the provisions of 23.15.2, and pursuant to 20.5.4.2.1, a program may specialize common_type<T1, T2> for types T1 and T2 such that is_same_v<T1, decay_t<T1>> and is_same_v<T2, decay_t<T2>> are each true. [Note: Such specializations are needed when only explicit conversions are desired between the template arguments. — end note ]

Such a specialization need not have a member named type, but if it does, that member shall be a typedef-name for an accessible and unambiguous cv-unqualified non-reference type C to which each of the types T1 and T2 is explicitly convertible. Moreover, common_type_t<T1, T2> shall denote the same type, if any, as does common_type_t<T2, T1>. No diagnostic is required for a violation of this Note’s rules.

基于此,我希望以下断言能够通过(它们会通过)...

static_assert(not std::is_const_v<std::common_type_t<const volatile int, short>>);
static_assert(not std::is_volatile_v<std::common_type_t<const volatile int, short>>);
static_assert(std::is_same_v<std::common_type_t<int, short>, std::common_type_t<short, const volatile int>>);
static_assert(std::is_same_v<std::common_type_t<int &, short>, std::common_type_t<int, short>>);

同样,我希望这些也能通过...

using D1 = std::chrono::duration<int, std::ratio<2, 20>>;
using D2 = std::chrono::duration<short, std::ratio<7, 100>>;
static_assert(not std::is_const_v<std::common_type_t<const D1, D2>>);
static_assert(not std::is_volatile_v<std::common_type_t<volatile D1, D2>>);
static_assert(std::is_same_v<std::common_type_t<D1, D2>, std::common_type_t<const D1, D2>>);
static_assert(std::is_same_v<std::common_type_t<D1 &, D2>, std::common_type_t<D1, D2>>);

但是,我在调用 std::common_type 时遇到编译器错误将任何简历限定符或引用添加到 std::chrono::duration .

对我来说,标准似乎表明第二组断言应该成功,但它们在 clang 和 gcc 中都失败了。因此,我假设我误读了标准 - 或者两家供应商都有相同的错误,这在某种程度上不太可能(另外,在打赌谁错了时,我总是和我一起去)。

也许“除非这个特性是特化的(如下文注释 B 中指定的)”这句话意味着注释 A 第 3.3 节的租户都没有申请特化,但这意味着我们可以合法地得到非常奇怪的结果...就像要求这个时的编译错误...

using D1 = std::chrono::duration<int, std::ratio<2, 20>>;
using D2 = std::chrono::duration<short, std::ratio<7, 100>>;
static_assert(not std::is_const_v<std::common_type_t<const D1, D2>>);

正常使用std::common_type不需要在调用它之前删除 cv 限定符和引用 - 但特化似乎要求调用者必须删除 cv 限定符和引用。

这似乎是错误的……某处。所以,我想弄清楚...规范、供应商实现或我的头脑是否有误?


更新

编译器资源管理器中的 gcc/trunk 似乎成功编译了我认为应该编译的所有内容,尽管 gcc 9.2 以及所有 clang 版本都失败了。

最佳答案

这似乎是您的 中的错误. 的当前版本没有错误,如 godbolt 所证明的那样.

3.3.1 确实要求它衰减参数并递归; 不这样做。

关于c++ - std::common_type 的特化 - 误解、错误、两者兼而有之?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58330207/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com