12

I was playing around with auto template parameters and I was surprised that this code didn't compiled:

constexpr auto bar = 2;

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

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

Visual Studio 15.7 (preview 4) spit out these errors:

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'

Then, after adding inline, the error got away!

constexpr inline auto bar = 2;

I thought constexpr variables were implicitly inline. Also, how does that affect the linkage of my variable bar?

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
  • 2
    @miradulo yeah of course... But GCC and Clang now also allows for reference or pointer to object of any linkage as a non-type template parameter. So either constexpr variable really should be inline and this is a visual studio bug, or GCC and Clang accept the variable but all have internal linkage. – Guillaume Racicot Apr 19 '18 at 05:09
  • Ahh, thanks for the explanation. – miradulo Apr 19 '18 at 05:13
  • for implicitly defined copy/move constructor, it is constexpr and inline. but not for primitive types. – Joseph D. Apr 19 '18 at 05:16

1 Answers1

26

Are all constexpr variable implicitly inline?

No. Only constexpr functions and constexpr static data members are implicitly inline ([dcl.constexpr]/1).

Also, how does that affect the linkage of my variable bar?

A constexpr variable is const ([dcl.constexpr]/9). A non-inline const variable that is not explicitly declared extern has internal linkage ([basic.link]/3).

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
cpplearner
  • 13,776
  • 2
  • 47
  • 72
  • 3
    Ah! This is where I got confused, the implicit inline is only for static data members constexpr, not all constexpr variables. – Guillaume Racicot Apr 19 '18 at 05:28
  • 3
    @GuillaumeRacicot you have the right to be confused, the original standard paper itself is wrong in that it does not mention that distinction. http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0386r0.pdf – v.oddou Apr 16 '20 at 08:16