Mitchk
Mitchk

Reputation: 13

Validation of an std::initializer_list in constexpr context

I have some class that I would like to be initialized at compile time by an initializer list that needs some level of validation.

I first tried static_assert but that wouldn't compile with the error "non-constant condition for static assertion"

What is the best way to causing a build error with this?

class foo {
public:
    constexpr foo(std::initializer_list<bar> items) {
        for(auto &&i: items) {
            if(i == 12) // example validation logic
                // fail the build
        }
    }
}

constexpr foo foo_list({0,1,2,3,4,5});// should succeed
constexpr foo foo_list_bad({0,1,12,4,68});// should fail to build

Upvotes: 1

Views: 82

Answers (1)

L. F.
L. F.

Reputation: 20619

Use a construct that cannot be used at compile time, e.g., an exception:

constexpr foo(std::initializer_list<bar> items)
{
    for (auto&& i : items) {
        if (i == 12) {
            throw std::invalid_argument{""}; // for example
        }
    }
}

or a false assertion if exception is disabled:

constexpr foo(std::initializer_list<bar> items)
{
    for (auto&& i : items) {
        assert(i != 12);
    }
}

or call a runtime function if NDEBUG is defined:

constexpr foo(std::initializer_list<bar> items)
{
    for (auto&& i : items) {
        if (i == 12) {
            std::cerr << "Error\n";
        }
    }
}

A diagnostic is required if runtime-only expressions are evaluated as a part of the evaluation of a constant expression.

static_assert does not work because the argument thereto is required to be a constant expression, which arguments to constexpr functions are not.

Upvotes: 1

Related Questions