2

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];
  }
}
1
  • yea sorry. If I was not clear I just want to have a single instance of values in my program, that is precomputed at compile time and then accessed through Space::foo at run time. Commented Feb 4, 2021 at 7:39

1 Answer 1

1

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);
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you a lot, but If I instead make Space a class with private static values and fill and public static foo, all defined in class (maybe I delete the constructor also), will I have multiple "values" if I include such class .hpp file in different TU? Intuitively a static member should only exists once in the entire program right? This way I could still do Space::foo but having values only existing once somewhere in the memory. I thought I could mimic this behaviour with namespaces, I will try to understand the consteval suggestion.
@lucmobz Yes, you could do that (but you don't need a class for that). You would need to declare it extern const ... values; and fill it in the .cpp file. That would however mean that the array will most probably be materialized even if it doesn't need to. In the above example, the compiler could optimize away the array and just return the evaluated result for values[10] + values[20]. The array doesn't even have to exist in the executable or in runtime.
I am reading that doing in a .hpp file namespace ns { inline constexpr int val = 10; } actually doesn't create copies of val in multiple TU (in c++17). Does my problem then solely originates from using the unnammed namespace? I could get rid of it (or call it detail) and the array values will exist only once in the entire code regardless how many TU are there?
@lucmobz Yes, or you could put it in a named namespace (detail is popular): example

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.