Consider a class that just wraps a value at runtime :
template <typename Type>
class NonConstValue
{
public:
NonConstValue(const Type& val) : _value(val) {;}
Type get() const {return _value;}
void set(const Type& val) const {_value = val;}
protected:
Type _value;
};
and the constexpr version of that:
template <typename Type>
class ConstValue
{
public:
constexpr ConstValue(const Type& val) : _value(val) {;}
constexpr Type get() const {return _value;}
protected:
const Type _value;
};
Question 1 : Can you confirm that the constexpr version is designed in the right way ?
Question 2 : How do you mix both classes into a single one called Value
that can be constexpr
constructed or runtime constructed and whose value can be get()
at runtime or compile-time ?
EDIT :
Question 3 : If get()
is defined in a .cpp
file, and if I want get()
to be inlined if it's not a constexpr
what is the right declaration of the function ? Is it
constexpr inline Type get();
or
inline constexpr Type get()
or something else ?
A const int var can be dynamically set to a value at runtime and once it is set to that value, it can no longer be changed. A constexpr int var cannot be dynamically set at runtime, but rather, at compile time. And once it is set to that value, it can no longer be changed.
The primary difference between const and constexpr variables is that the initialization of a const variable can be deferred until run time. A constexpr variable must be initialized at compile time. All constexpr variables are const .
#define directives create macro substitution, while constexpr variables are special type of variables. They literally have nothing in common beside the fact that before constexpr (or even const ) variables were available, macros were sometimes used when currently constexpr variable can be used.
constexpr stands for constant expression and is used to specify that a variable or function can be used in a constant expression, an expression that can be evaluated at compile time. The key point of constexpr is that it can be executed at compile time.
Just add the constexpr
specifier to each of those functions that are potential constant expressions.
template <typename Type>
class Value
{
public:
constexpr Value(Type const& val) : _value(val) {}
constexpr Type const& get() const {return _value;}
void set(Type const& val) {_value = val;}
protected:
Type _value;
};
You don't need a const and a non-const version, since that can be done by instantiating the template Value
with a const or non-const type.
You don't need a constexpr and a non-constexpr version, constexpr
means potential constant expression and whether the expression ends up being a constant expression or not depends on its arguments. Whether or not the expression ends up being evaluated at compile-time depends on the context and the implementation.
Your constexpr
class is designed correctly, except that you mistyped the name of the constructor (it should be ConstValue
, not Value
). But I'm sure that's just a typo.
Instances of your constexpr
version can be used both as compile-time and as run-time objects.
template <typename Type>
class ConstValue
{
public:
constexpr ConstValue(const Type& val) : _value(val) {;}
constexpr Type get() const {return _value;}
protected:
const Type _value;
};
int main(int argc, char* argv[])
{
int x[ConstValue<int>(3).get()];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With