【发布时间】:2021-08-12 19:15:00
【问题描述】:
考虑以下 MCVE 代码:
struct Id { static inline int id(int c) {return c;} };
template <class C>
class Foo {
C m_bar;
public:
Foo() = default;
Foo(int) : m_bar{bar} {} // Fails in clang, compiles in gcc/msvc
Foo(int, int) : m_bar(bar) {} // Compiles with all gcc/clang/msvc
Foo(int, int, int) : m_bar(Id::id(bar)) {} // Compiles in gcc/msvc with both () and {} syntax, fails for both in clang
C bar() const { return m_bar; }
};
为简单起见,假设我实例化了Foo<int> x;。我希望所有的构造函数都会产生编译错误,因为我正在尝试用bar 初始化m_bar,这是一个方法(并不是我没有在这里调用bar) .
但所有变体都可以在所有主要编译器上编译,唯一的例外是 Foo(int) 中的 clang。
请注意,当我调用相应的构造函数重载时,所有编译器都会按预期失败,例如Foo<int> f{1};。但据我了解,class 是一个模板,而不是 构造函数,所以我希望所有构造函数在实例化类模板时都会失败,即使是未使用的构造函数.
有趣的是,当使用如下所示的非模板类时,所有三个构造函数都按预期失败:
class Foo {
int m_bar;
public:
Foo() = default;
Foo(int) : m_bar{bar} {} // fails in all gcc/clang/msvc
Foo(int, int) : m_bar(bar) {} // fails in all gcc/clang/msvc
Foo(int, int, int) : m_bar{Id::id(bar)} {} // fails in all gcc/clang/msvc
int bar() const { return m_bar; }
};
为方便起见,这里是带有编译器输出的godbolt 链接。
我的问题是:这是所有三个编译器中的一个错误,还是我这边有一些误解,也许是标准中解释这种行为的一些晦涩的部分?
【问题讨论】:
-
你能在这篇文章中添加一个minimal reproducible example 的代码和它给你的错误吗?不是很多人喜欢点击链接并不得不编辑代码来尝试和预先产生问题。
-
#if 1是否意味着切换错误?我尝试了#if 0和#if 1,所有编译器都编译得很好。 -
另外,那个godbolt链接不会永远存在,如果链接上的信息是理解问题所必需的,那么这个问题在不久的将来就会“无用”。
-
@NathanOliver:这实际上是可重现的例子。使用快速命令编译 sn-p 就足够了。
Foo的实例化是可选的。这是我缺少的错误消息,所以也没有太多可显示的。如果有帮助,我可以用语言律师标签标记它。 -
我不确定为什么只有 clang 会捕获它,但请尝试使用其他构造函数之一(例如
Foo(5)此处为 godbolt.org/z/c6codf1x5)。全部失败
标签: c++ visual-c++ g++ clang language-lawyer