Передача объектов 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. Это привело меня к следующим вопросам:
- Правильна ли моя интерпретация?
Почему это поведение диктует стандарт?
Я не вижу проблемы в прохождении
constexpr
объект вокруг. Конечно, я мог бы переписать свой код, чтобы он поместился в одну функцию, но это приводит к ограниченному коду. Я бы предположил, что разделение отдельных функций на отдельные блоки кода (функции) должно быть хорошим стилем и для операций времени компиляции.- Как я уже говорил, ошибку компилятора можно устранить, перемещая код из тел отдельных функций тестирования (таких как
numOpen
) в тело функции верхнего уровняcheck
, Однако мне не нравится это решение, так как оно создает одну огромную и тесную функцию. Видите ли вы другой подход к решению проблемы?
1 ответ
Причина в том, что внутри constexpr
функция, параметры не являются константными выражениями, независимо от того, являются ли аргументы. Ты можешь позвонить constexpr
функции внутри других, но параметры constexpr
функция не constexpr
внутри, делая любой вызов функции (даже constexpr
функции) не константное выражение - внутри.
const auto nOpen = numOpen( str );
Достаточно Только после просмотра звонка извне constexpr
правильность выражений внутри проверяется, решая, является ли весь вызов constexpr
или нет.