5

I am trying to create a namespace-scope constant with external linkage

// in some include file:

namespace foo 
{
    constexpr double bar() { return 1.23456; } // internal linkage
    constexpr double baz = 1.23456;            // internal linkage
    const double bing = 1.23456;               // internal linkage
}

Is this even possible?

Steve Lorimer
  • 27,059
  • 17
  • 118
  • 213

2 Answers2

10

Yes, and no; you can use extern:

[C++11: 3.5/3]: A name having namespace scope (3.3.6) has internal linkage if it is the name of

  • a variable, function or function template that is explicitly declared static; or,
  • a variable that is explicitly declared const or constexpr and neither explicitly declared extern nor previously declared to have external linkage; or
  • a data member of an anonymous union.

So:

namespace foo 
{
    extern constexpr double bar() { return 1.23456; }
    extern constexpr double baz = 1.23456;
}

In your other translation unit, you should now be able to declare the function's name and refer to it:

#include <iostream>

namespace foo
{
   extern constexpr double bar();
}

int main()
{
   std::cout << foo::bar() << '\n';
}

However, the rules for constexpr variables state that you cannot have a declaration that is not also a definition:

[C++11: 7.1.5/9]: A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. [..]

So, you cannot take the same approach with baz.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • What would happen if the file was included? – Red XIII Jan 31 '13 at 10:28
  • @RedXIII: Inclusion is irrelevant; `#include` is a strict text-based replacement performed by the pre-processor; this question relates to the compilation phases. i.e. you can replace every line of my example with an `#include` directive that refers to a file containing that line, if you like, but it won't change my answer. :) – Lightness Races in Orbit Jan 31 '13 at 11:35
  • I was referring to your comment that "*you cannot have a declaration that is not a definition for `constexpr`*". This way you wouldn't have to `extern` the externally implemented `constexpr` and thus use it. – Red XIII Jan 31 '13 at 18:33
  • @RedXIII: You mean you're talking about simply creating identical internal-linkage definitions for the symbol in each translation unit, using a header? Okay, yes, fine, but that's not what the question is about. – Lightness Races in Orbit Feb 01 '13 at 01:23
0

constexpr for functions implies inline, which implies external linkage. So you already have what you want for bar. As for baz and bing, you can also declare them inline in C++17.

See also https://stackoverflow.com/a/4193698/261217

Mikhail
  • 20,685
  • 7
  • 70
  • 146