考虑以下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;。我希望所有的构造函数都会产生编译错误,因为我试图用m_bar初始化bar,这是一种方法(并不是说我没有在这里调用bar )。
但是所有变体都在所有主要编译器上编译,只有Foo(int)中的clang例外。
注意,当我调用相应的构造函数重载(例如Foo<int> f{1}; )时,所有编译器都会按预期失败。但据我所知,类是模板,而不是构造函数,所以我希望所有构造函数在实例化类模板时失败,即使是未使用的类模板。
有趣的是,当使用如下所示的非模板类时,所有三个构造函数都如预期的那样失败:
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; }
};为了方便起见,下面是带有编译器输出的哥德波特链接。
我的问题是:这是三个编译器中的一个bug,还是我的错误观念,也许是标准中一些不明确的部分解释了这种行为?
发布于 2021-08-12 21:54:24
类模板成员按需实例化。请参阅[temp.inst]/9
除非需要实例化,否则实现不应隐式实例化函数模板、变量模板、成员模板、非虚拟成员函数、成员类、类模板的静态数据成员,或constexpr语句的子语句。
另外,由于m_bar依赖于模板参数,所以在模板解析期间不能检查表达式m_bar{bar}。
https://stackoverflow.com/questions/68763023
复制相似问题