1

Following up on Why does cppreference define type_traits xxx_v shortcuts as inline constexpr and not just constexpr?, if I make my own type trait and want to avoid ODR violations and want it to be compatible with pre-C++17 projects, is putting the xxx_v shortcut in an anonymous namespace the same as explicitly declaring it inline?

For example, taking all_true from Check traits for all variadic template arguments, with C++17 I can write in my utility header:

template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
template <bool... v>
inline constexpr bool all_true_v = all_true<v...>::value;

Is that the same as writing the following code which is compatible with pre-C++17?

template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
namespace {
   template <bool... v>
   constexpr bool all_true_v = all_true<v...>::value;
}
Danra
  • 9,546
  • 5
  • 59
  • 117
  • 4
    The unnamed namespace gives everything within internal linkage... And `all_true_v` has internal linkage anyway for the very same reason @Oliv quoted on your other question (same bullet in C++14). So the two code snippets you presented aren't at all compatible. – StoryTeller - Unslander Monica Jan 03 '18 at 13:11
  • @StoryTeller Of course. My mix up. – Danra Jan 03 '18 at 17:00

2 Answers2

3

consider

    bool const* g_b= &all_true_v<true>;

this will have the same address in every translation unit for the inline constexpr version, but different adresses for the namespace {} version.

Tobi
  • 2,591
  • 15
  • 34
2

You do avoid the ODR violation with the anonymous namespace, as it creates a new separate set of objects in each file where it is included. The advantage of an inline object is that there will only be one in total.

However, if you only use the constexpr values as constants, you will not notice much of a difference. And a nice compiler might avoid storing the constants in the data area anyway.

Passing references or pointers around and comparing addresses could make a difference, like Tobi says. But perhaps you can avoid comparing the addresses of two constant values?

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • `constexpr` already implies `static` here, so it doesn't really do anything to put them in an unnamed namespace. That said, you can definitely get ODR problems by defining templates or inline functions that _use_ these multiply-defined constants. That's why inline variables were added in the first place. – Davis Herring Nov 29 '22 at 07:05