传递constexpr对象 [英] Passing constexpr objects around
问题描述
我决定给予新的 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 [] 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 if(str [idx] =='{'){++ numOpen; }
else if(str [idx] =='}'){--numOpen; }
++ idx;
}
return numOpen;
}
constexpr bool check(const str_const& str){
constexpr auto nOpen = numOpen(str);
// ...
//应用更多此处的测试函数,
//每个返回一个编码输入正确性的变量
// ...
return(nOpen == 0 / *&& ...测试变量... * /);
}
int main(){
constexpr str_const s1 {{Foo:Bar} {Quooz:Baz}};
constexpr auto pass = check(s1);
}
我使用 str_const
/ cpp11-new-tools-for-class-and-library-authors /rel =nofollow> Scott Schurr at C ++ Now 2012 in a version modified for 上面的代码将无法编译时出现错误(
clang-3.5 $>)。
< c $ c>)
错误:constexpr变量'nOpen'必须由常量表达式初始化
constexpr auto nOpen = numOpen(str);
~~~~~~~~~ ^ ~~~~
结论是你不能传递 constexpr
对象,而不会丢失它的 constexpr
-ness。这导致以下问题:
- 我的解释是否正确?
-
这是标准规定的行为吗?
我没有看到在传递
constexpr
对象的问题。当然,我可以重写我的代码,以适应单一的功能,但这导致狭窄的代码。 - 正如我前面说过的编译器错误可以解决通过将单独测试函数(如
numOpen
)的代码移动到顶层函数的主体检查
。但是,我不喜欢这个解决方案,因为它创造了一个巨大的和狭窄的功能。您是否看到了解决问题的不同方法?
> inside a constexpr
函数中,参数不是常量表达式,无论参数是否为。你可以在其他函数中调用 constexpr
函数,但 constexpr
函数的参数不是 constexpr
,使任何函数调用(即使是 constexpr
函数)不是常量表达式 inside 。
const auto nOpen = numOpen
Suffices 。只有当您查看来自 之外的调用时,验证了表达式的 constexpr
- 的值,才能确定整个调用是否 constexpr
或不。
I decided to give then new C++14
definition of constexpr
a spin and to get the most out of it I decided to write a little compile-time string parser. However, I'm struggling with keeping my object a constexpr
while passing it to a function. Consider the following code:
#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 );
}
I uses the str_const
class presented by Scott Schurr at C++Now 2012 in a version modified for C++14
.
The above code will fail to compile with the error (clang-3.5
)
error: constexpr variable 'nOpen' must be initialized by a constant expression
constexpr auto nOpen = numOpen( str );
~~~~~~~~~^~~~~
Which leads me to the conclusion that you can not pass around a constexpr
object without losing its constexpr
-ness. This lead me to the following questions:
- Is my interpretation correct?
Why is this the behaviour the standard dictates?
I don't see the problem in passing a
constexpr
object around. Sure, I could rewrite my code to fit into a single function, but that leads to cramped code. I would assume that factoring separate functionality into separate units of code (functions) should be good style for compile time operations too.- As I said before the compiler error can be solved by moving the code from the bodies of separate testing functions (such as
numOpen
) into the body of the top-level functioncheck
. However, I don't like this solution since it creates one huge and cramped function. Do you see a different approach to solving the problem?
The reason is that inside a constexpr
function, parameters aren't constant expressions, regardless of whether the arguments are. You can call constexpr
functions inside others, but the parameters of a constexpr
function aren't constexpr
inside, making any function call (even to constexpr
functions) not a constant expression - inside.
const auto nOpen = numOpen( str );
Suffices. Only once you view the call from outside the constexpr
-ness of the expressions inside is verified, deciding whether the whole call is constexpr
or not.
这篇关于传递constexpr对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!