Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design of constexpr classes : merging constexpr and non-constexpr versions?

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 ?

like image 776
Vincent Avatar asked Jan 18 '13 00:01

Vincent


People also ask

Can constexpr be changed?

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.

Should I use constexpr or const?

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 .

Why is constexpr better than #define?

#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.

What does constexpr mean in C++?

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.


2 Answers

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.

like image 85
K-ballo Avatar answered Sep 29 '22 07:09

K-ballo


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()];
}
like image 43
Andy Prowl Avatar answered Sep 29 '22 06:09

Andy Prowl