【问题标题】:Different types of `decltype((const int)a)` and `decltype((const int)1)``decltype((const int)a)` 和 `decltype((const int)1)` 的不同类型
【发布时间】:2018-05-28 04:23:17
【问题描述】:
// g++ 7.3
template<typename T>
struct td;

int main()
{
  int a = 1;

  td<decltype((const int)a)> t1;
  td<decltype((const int)1)> t2;

  return 0;
}

下面是编译的输出:

错误:聚合 ‘td&lt;int&gt; t1’ 的类型不完整,无法定义
错误:聚合 ‘td&lt;const int&gt; t2’ 的类型不完整,无法定义

那么,为什么decltype((const int)a) 和decltype((const int)1) 的类型不同呢?

【问题讨论】:

  • 请以文本形式而不是图像形式发布编译器消息。文本内容易于搜索。
  • 它也易于访问。
  • 以防万一有人不知道:OP 正在使用“类型显示”技巧通过编译器错误消息显示类型。
  • 我的实验表明 GCC 7.3 和 8.1 的行为不同。 godbolt.org/g/cjNLAF

标签: c++ type-conversion decltype


【解决方案1】:

说明符decltype((const int)a) 和decltype((const int)1) 都解析为int。这是因为没有 const 非类类型的纯右值,如 C++17 [expr] 中所述:

如果纯右值最初的类型为 cv T,其中 T 是无 cv 限定的非类、非数组类型,则在进行任何进一步分析之前,表达式的类型将调整为 T。

您的输出可能只是诊断消息中的错误。要确认编译器错误,您可以编写一些行为根据 decltype 结果而有所不同的代码,例如:

decltype((const int)1) x;  x = 5;

应该编译成功。

【讨论】:

    【解决方案2】:

    不是答案,只是补充数据。

    以下代码,

    template< class Type > struct T{ Type x; };
    
    int main()
    {
        int a = 1;
        T<decltype((const int)a)> t1; t1.x = 1;
        T<decltype((const int)1)> t2; t2.x = 2;
    }
    

    ... 使用 Visual C++ 2017 可以干净地编译,但不能使用 MinGW g++ 7.2.0:

    [P:\温度] > g++ foo.cpp foo.cpp:在函数'int main()'中: foo.cpp:7:31:错误:使用已删除的函数 'T::T()' T t2; t2.x = 2; ^~ foo.cpp:1:31:注意:'T::T()' 被隐式删除,因为默认定义格式不正确: ∩╗┐template struct T{ Type x; }; ^ foo.cpp:1:31: 错误:'struct T' 中未初始化的 const 成员 foo.cpp:1:39: 注意:'const int T::x' 应该被初始化 ∩╗┐template struct T{ Type x; }; ^ foo.cpp:7:42:错误:分配只读成员 'T::x' T t2; t2.x = 2; ^ [P:\温度] > _

    这表明存在 g++ 编译器错误。

    【讨论】:

    • 出于兴趣,如果您将a 声明为const int a = 1;,MSVC 会做什么?我记得他们确实或曾经有一个“转换为左值”扩展,其中将左值转换为相同的类型会产生一个左值(而在 ISO C++ 中它始终是一个纯右值)
    • 这也编译干净。
    猜你喜欢
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 2011-11-07
    • 1970-01-01
    • 2010-11-11
    相关资源
    最近更新 更多