Reputation: 9916
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;
}
Upvotes: 1
Views: 1023
Reputation: 92341
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?
Upvotes: 2
Reputation: 2749
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.
Upvotes: 3