【问题标题】:Possible compiler bug in MSVCMSVC 中可能的编译器错误
【发布时间】:2019-12-31 17:00:12
【问题描述】:

以下代码使用 gcc 和 clang(以及许多其他 C++11 编译器)编译

#include <stdint.h>

typedef int datatype;

template <typename T>
struct to_datatype {};

template <>
struct to_datatype<int16_t> {
  static constexpr datatype value = 1;
};

template <typename T>
class data {
 public:
  data(datatype dt = to_datatype<T>::value) {}
};

int main() {
  data<char> d{to_datatype<int16_t>::value};
}

当使用(几乎)最新的 MSVC 编译时

> cl .\test.cpp /std:c++latest /permissive-
Microsoft (R) C/C++ Optimizing Compiler Version 19.24.28314 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
.\test.cpp(16): error C2039: 'value': is not a member of 'to_datatype<T>'
        with
        [
            T=char
        ]
.\test.cpp(16): note: see declaration of 'to_datatype<T>'
        with
        [
            T=char
        ]
.\test.cpp(20): note: see reference to class template instantiation 'data<char>' being compiled

这是 MSVC 的错误吗?如果是,C++ 标准中的哪个术语最能描述它?

如果将部分代码替换为

template <typename T>
class data {
 public:
  data(datatype dt) {}
  data() : data(to_datatype<T>::value) {}
};

反正编译很顺利。

【问题讨论】:

  • 这一行可以解释这些差异。查看您的编译器为std::is_same_v&lt;char, int8_t&gt; 返回的内容。我的猜测是,int8_t 是否与 char 相同是实现定义的,但需要检查文档。
  • 看起来它实际上可能是一个错误。 This issue最近开了,还有其他几起报道。
  • @alteredinstance 我看不出这个问题与这个问题有什么关系,或者你以前的链接是如何做的。您是否只是复制了 google 针对此错误消息提供的第一个链接?错误消息非常笼统,可能出现在许多不同(合法)的情况下。
  • @walnut Line 231 of the code mentioned in the issue 与聚合初始化的 MSVC 问题的链接失效,OP 的代码正在做同样的事情。碰巧的是,boost 库最近遇到了类似的问题,在 MSVC 的聚合类型中使用value

标签: c++ c++11 visual-c++


【解决方案1】:

我会说 MSVC 不接受代码是错误的。

根据C++17标准最终草案[dcl.fct.default]/5,类模板的成员函数的默认参数中的名称查找是根据[temp.inst]中的规则进行的。

根据[temp.inst]/2 类模板的隐式实例化不会导致成员函数的默认参数的实例化,并且根据[temp.inst]/4 一个(a 的非显式特化)类模板的成员函数的默认参数是在被调用使用时实例化。

在您的代码中没有使用默认参数to_datatype&lt;T&gt;::value 的调用,因此不应实例化它。因此,在 to_datatype&lt;char&gt; 中查找 value 失败时不应该出现错误。

(C++11标准终稿中的相关部分有等价的措辞,除了编号,请参见[decl.fct.default]/5[temp.inst]/1[temp.inst]/3。)

【讨论】:

    最近更新 更多