我决定给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 );
}
我在为C++14
修改的版本中使用str_const
class提供的Scott Schurr at C++Now 2012。
上述代码无法使用错误(clang-3.5
)
error: constexpr variable 'nOpen' must be initialized by a constant expression
constexpr auto nOpen = numOpen( str );
~~~~~~~~~^~~~~
这使我得出的结论是,在不丢失constexpr
的情况下,您无法传递constexpr
个对象。这引出了以下问题:
为什么这是标准规定的行为?
我没有看到传递constexpr
对象的问题。当然,我可以重写我的代码以适应单个函数,但这会导致代码变得狭窄。我认为将单独的功能分解为单独的代码单元(函数)也应该是编译时操作的好方式。
numOpen
)的主体移动到顶级函数的主体中来解决{ {1}}。但是,我不喜欢这个解决方案,因为它创造了一个庞大而狭窄的功能。您是否看到了解决问题的不同方法?答案 0 :(得分:6)
原因是内部一个constexpr
函数,参数不是常量表达式,无论参数是否为。您可以在其他人中调用constexpr
个函数,但constexpr
函数的参数不在{/ 1}} 里面,进行任何函数调用(甚至{{1}函数)不是常量表达式 - 里面。
constexpr
Suffices。只有当您从外部查看来电时,才会验证内部表达式的constexpr
,并确定整个来电是否为const auto nOpen = numOpen( str );
。