vendredi 3 juin 2022

Builder patterns with vectors evaluated at compile time (with `consteval`)

I am attempting to create a class that follows the builder pattern and also runs completely at compile time (with the use of the new consteval keyword in C++20), but whatever I try doesn't work. For example, this won't work:

#include <vector>

class MyClass
{
private:
    std::vector<int> data;

public:
    consteval MyClass& setData()
    {
        this->data = {20};
        return *this;
    }

    consteval std::vector<int> build()
    {
        return data;
    }
};


int main()
{
    std::vector<int> data = MyClass().setData().build();
}

Which gives the error "<anonymous> is not a constant expression". This led me to believe I should instead return copies of the class instead:

#include <vector>

class MyClass
{
private:
    std::vector<int> data;

public:
    consteval MyClass setData()
    {
        // https://herbsutter.com/2013/04/05/complex-initialization-for-a-const-variable/
        return [&]{
            MyClass newClass;
            newClass.data = {20};
            return newClass;
        }();
    }

    consteval std::vector<int> build()
    {
        return data;
    }
};


int main()
{
    std::vector<int> data = MyClass().setData().build();
}

Yet, I got the same error. How should I use a constant-time builder pattern in C++? It seems this only occurs with vectors, and I am using a version which supports C++20 constexpr vectors.

Aucun commentaire:

Enregistrer un commentaire