Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ constexpr count constructor calls

I'm trying to static instantiate some objects at compile time. What I need is to set to a member int variable an incremented value. For example, the first object I create will have the 0 value, the second 1, the third 2... Summarizing I need something like this but it has to work as constexpr.

//header
class MyClass final {
private:
    static int IDcount;
public:
    const int ID;
    constexpr MyClass(args);
    //~MyClass();
};
//source
int MyClass::IDcount = 0;
constexpr MyClass::MyClass(args) : ID(MyClass::IDcount++) {
}

Is there a way to achieve this at compile time (without taking the ID as argument of the constructor)

like image 462
barsan-md Avatar asked Oct 23 '14 13:10

barsan-md


2 Answers

It can't be done the way you've defined it, but there is a non-standard but widely implemented preprocessor trick that could be employed.

#include <iostream>

struct MyClass final {
    constexpr MyClass(int myid, const char *myname)
        : id(myid), name(myname) {}
    int id;
    const char *name;
};

constexpr MyClass m[]{ 
    MyClass(__COUNTER__, "Larry"),
    MyClass(__COUNTER__, "Moe"),
    MyClass(__COUNTER__, "Curly")
};

int main()
{
    for (auto const &obj : m)
        std::cout << obj.id << '\t' << obj.name << "\n";
}

The __COUNTER__ macro is defined in Microsoft's Visual C++, gcc since version 4.3 and clang.

When run, this program produces:

0   Larry
1   Moe
2   Curly
like image 57
Edward Avatar answered Nov 03 '22 10:11

Edward


A constexpr-function or ctor must be a valid core constant expression on at least one path:

7.1.5 The constexpr specifier [dcl.constexpr]

5 For a non-template, non-defaulted constexpr function or a non-template, non-defaulted, non-inheriting constexpr constructor, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (5.19), the program is ill-formed; no diagnostic required.

Which means it cannot modify a global object on all paths:

5.19 Constant expressions [expr.const]

  1. A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:

    • modification of an object (5.17, 5.2.6, 5.3.2) unless it is applied to a non-volatile lvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e;
like image 29
Deduplicator Avatar answered Nov 03 '22 09:11

Deduplicator