Валидация списка std :: initializer_list в контексте constexpr - PullRequest
1 голос
/ 21 февраля 2020

У меня есть некоторый класс, который я хотел бы инициализировать во время компиляции списком инициализаторов, который требует некоторого уровня проверки.

Сначала я попробовал static_assert, но он не скомпилируется с ошибкой " константное условие для утверждения c "

Каков наилучший способ вызвать ошибку сборки при этом?

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

1 Ответ

1 голос
/ 21 февраля 2020

Используйте конструкцию, которую нельзя использовать во время компиляции, например, исключение:

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

или ложное утверждение, если исключение отключено:

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

, или вызов времени выполнения функция, если определено NDEBUG:

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

Диагностика c требуется, если выражения только во время выполнения оцениваются как часть оценки константного выражения.

static_assert не работает, потому что аргумент к нему должен быть константным выражением, а аргументы constexpr - нет.

...