【问题标题】:Passing constexpr objects around传递 constexpr 对象
【发布时间】:2014-12-04 10:42:02
【问题描述】:

我决定对constexpr 的新C++14 定义进行一次旋转,为了充分利用它,我决定编写一个小的编译时字符串解析器。但是,在将对象传递给函数时,我正在努力保持对象为 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修改的版本中使用Scott Schurr at C++Now 2012提供的str_const class

上面的代码会编译失败,报错(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的主体中来解决.但是,我不喜欢这种解决方案,因为它创建了一个庞大而狭窄的功能。您是否看到了解决问题的不同方法?

【问题讨论】:

  • 你看到解决问题的不同方法了吗? constexpr auto nOpen = numOpen( str ); instance 不需要是 constexpr 来在编译时评估函数

标签: c++ c++14 constexpr


【解决方案1】:

原因是constexpr函数内,参数不是常量表达式,不管参数是否是。您可以在其他函数内部调用constexpr 函数,但constexpr 函数的参数不是constexpr inside,使得任何函数调用(甚至对constexpr 函数)都不是常量表达式- 里面

const auto nOpen = numOpen( str );

Suffices。只有在您从外部查看调用时,才会验证内部表达式的constexpr-ness,从而确定整个调用是否为constexpr

【讨论】:

  • 我猜这意味着不可能从传递给该函数的字符串文字在函数内创建constexpr 对象?这是一个耻辱,因为我想将check 函数包装在我的实际解析器中。 this(非编译)模拟代码之类的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-17
  • 1970-01-01
  • 2015-11-21
  • 2010-09-12
  • 1970-01-01
  • 2013-11-24
相关资源
最近更新 更多