Reputation: 5265
In the following code, I'm taking address to static constexpr member:
struct component_type_data{};
template<class Derived>
class component{
private:
const constexpr static component_type_data type_data{};
public:
static constexpr const component_type_data* component_type = &type_data;
};
My motivation is to have compile time unique id for type.
Is this valid? Code compiles only starting from C++17. And I can use that pointer as template argument.
If this valid, how compiler can know address beforehand?
UPDATE :
Also, what happens across dll boundaries? Each dll will have its own unique address for the same static member, or they will be the same?
Upvotes: 3
Views: 831
Reputation: 119487
Is this valid?
Yes; a constexpr
pointer object is allowed to contain the address of any object of static storage duration.
Code compiles only starting from C++17.
Prior to C++17, static constexpr
data members require an out-of-class definition as well:
template <class Derived>
constexpr const component_type_data component<Derived>::type_data;
template <class Derived>
constexpr const component_type_data* component<Derived>::component_type;
If this valid, how compiler can know address beforehand?
If you mean the numerical address: the answer is that the compiler cannot, in general, know that, as it may not be assigned until link time or possibly even until the program is loaded by the operating system.
However, the reason why addresses can be used as constant expressions is that the compiler effectively represents them symbolically, i.e., "address of component<int>::type_data
". If you were to then dereference such a pointer at compile time, the compiler would know that the result is "lvalue referring to component<int>::type_data
". So compile-time computation in C++ is really quite complicated and involves a lot of metadata (in the post-C++17 world, we really expect a lot from our compilers). Note that once you attempt to examine the numerical address (i.e., using reinterpret_cast
) you no longer have something that is usable at compile time.
Upvotes: 7