Передача объектов constexpr вокруг

Я решил дать тогда новый C++14 значение constexpr Я решил написать небольшой синтаксический анализатор строк во время компиляции. Тем не менее, я борюсь с сохранением моего объекта в constexpr при передаче его функции. Рассмотрим следующий код:

#include <cstddef>
#include <stdexcept>

class str_const {
    const char * const p_;
    const std::size_t sz_;
public:
    template <std::size_t N>
    constexpr str_const( const char( & a )[ N ] )
    : p_( a ), sz_( N - 1 ) {}
    constexpr char operator[]( std::size_t n ) const {
        return n < sz_ ? p_[ n ] : throw std::out_of_range( "" );
    }
    constexpr std::size_t size() const { return sz_; }
};

constexpr long int numOpen( const str_const & str ){
    long int numOpen{ 0 };
    std::size_t idx{ 0 };
    while ( idx <  str.size() ){
        if ( str[ idx ] == '{' ){ ++numOpen; }
        else if ( str[ idx ] == '}' ){ --numOpen; }
        ++idx;
    }
    return numOpen;
}

constexpr bool check( const str_const & str ){
    constexpr auto nOpen = numOpen( str );
    // ...
    // Apply More Test functions here,
    // each returning a variable encoding the correctness of the input
    // ...

    return ( nOpen == 0 /* && ... Test the variables ... */ );
}

int main() {
    constexpr str_const s1{ "{ Foo : Bar } { Quooz : Baz }" };
    constexpr auto pass = check( s1 );
}

Я использую str_const класс, представленный Скоттом Шурром на C++Now 2012 в версии, измененной для C++14,

Приведенный выше код не скомпилируется с ошибкой (clang-3.5)

error: constexpr variable 'nOpen' must be initialized by a constant expression  
    constexpr auto nOpen = numOpen( str );  
                           ~~~~~~~~~^~~~~

Что приводит меня к выводу, что вы не можете обойти constexpr объект, не теряя своего constexpr-ness. Это привело меня к следующим вопросам:

  1. Правильна ли моя интерпретация?
  2. Почему это поведение диктует стандарт?

    Я не вижу проблемы в прохождении constexpr объект вокруг. Конечно, я мог бы переписать свой код, чтобы он поместился в одну функцию, но это приводит к ограниченному коду. Я бы предположил, что разделение отдельных функций на отдельные блоки кода (функции) должно быть хорошим стилем и для операций времени компиляции.

  3. Как я уже говорил, ошибку компилятора можно устранить, перемещая код из тел отдельных функций тестирования (таких как numOpen) в тело функции верхнего уровня check, Однако мне не нравится это решение, так как оно создает одну огромную и тесную функцию. Видите ли вы другой подход к решению проблемы?

1 ответ

Решение

Причина в том, что внутри constexpr функция, параметры не являются константными выражениями, независимо от того, являются ли аргументы. Ты можешь позвонить constexpr функции внутри других, но параметры constexpr функция не constexpr внутри, делая любой вызов функции (даже constexpr функции) не константное выражение - внутри.

const auto nOpen = numOpen( str );

Достаточно Только после просмотра звонка извне constexprправильность выражений внутри проверяется, решая, является ли весь вызов constexpr или нет.

Другие вопросы по тегам