Search code examples
c++inlineconstexprc++20linkage

Inline constexpr and anonymous namespace variables?


I have the following problem. In a .hpp file I have a function Space::foo() that must use a namespace global variable, I thought of hiding it in an anonymous namespace. But now I wonder, do I risk having values defined in each translation unit with multiple copies or there will only be one? Thanks for helping. This comes from the fact that I needed a bunch of functions in the Space namespace with a sort of private data part (the anonymous namespace stuff) so that Space is sort of like a class with only static members, but I don't want to have multiple copies of these variables if I include the .hpp file in different units.

// .hpp file
#include <array>

namespace Space {
namespace {
  constexpr std::array<int, 10000> fill() { /* ... */ };
  inline constexpr std::array<int, 10000> values = fill();
}
  inline int foo(int i) {
    return values[i];
  }
}

Solution

  • do I risk having values defined in each translation unit with multiple copies

    Yes. You'll have one definition of values in each TU. You can't declare it extern constexpr either because [dcl.constexpr]/1 says "The constexpr specifier shall be applied only to the definition of a variable".

    Since the purpose seems to be to be able to pick values that are constant evaluated you could possibly make both fill and foo consteval and skip <anonymous>::values.

    namespace Space {
        namespace {
            consteval std::array<int, 10000> fill() {
                return {}; // replace with your filling algorithm
            };
        }
    
        inline consteval int foo(size_t i) {
            return fill()[i];
        }
    
        inline consteval int bar(size_t i, size_t j) {
            constexpr auto values = fill();
            return values[i] + values[j];
        }
    }
    

    This would make it possible for foo and any other consteval function to use the algorithm in fill() and to use the result in constexpr/consteval situations.

    constexpr auto x = Space::bar(10, 20);