所有的constexpr变量都隐式地是内联的吗?

12

我在尝试使用自动模板参数时,惊讶地发现这段代码无法编译:

constexpr auto bar = 2;

template<auto& T>
struct Foo {
    auto operator()() const { return T; }
};

int main() {
    Foo<bar> b;
    b();
}

Visual Studio 15.7(预览版4)会输出以下错误:

error C2970: 'Foo': template parameter 'T': 'bar': an expression involving objects with internal linkage cannot be used as a non-type argument
 note: see declaration of 'Foo'
 note: see declaration of 'bar'
error C2440: 'specialization': cannot convert from 'int' to 'int &'
 note: see reference to class template instantiation 'Foo<0>' being compiled
error C2973: 'Foo': invalid template argument 'int'
 note: see declaration of 'Foo'
然后,在添加了 "inline" 后,错误消失了!
constexpr inline auto bar = 2;

我以为constexpr变量是隐式inline的。此外,这会如何影响我的变量bar的链接?


2
@miradulo 当然可以... 但是GCC和Clang现在也允许将任何链接对象的引用或指针作为非类型模板参数。因此,constexpr变量应该真正是内联的,这是Visual Studio的一个错误,或者GCC和Clang接受该变量但都具有内部链接。 - Guillaume Racicot
啊,谢谢你的解释。 - miradulo
对于隐式定义的复制/移动构造函数,它是constexpr和inline的。但对于原始类型不是这样。 - Joseph D.
1个回答

26
所有的constexpr变量是否都会自动内联?
不是。只有constexpr函数和constexpr静态数据成员是隐式内联的([dcl.constexpr]/1)。
另外,这会影响变量bar的链接吗?
constexpr变量是const类型的([dcl.constexpr]/9)。一个非内联的const变量如果没有显式声明为extern,则具有内部链接性([basic.link]/3)。

3
啊!这就是让我感到困惑的地方,隐式内联仅适用于静态数据成员的constexpr,而不是所有的constexpr变量。 - Guillaume Racicot
3
@GuillaumeRacicot 你有权感到困惑,因为原始标准文件本身存在错误,它没有提到这个区别。http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0386r0.pdf - v.oddou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接