【问题标题】:constexpr constructor and functionsconstexpr 构造函数和函数
【发布时间】:2015-06-27 09:45:22
【问题描述】:

我有这个类 encrypted_string,它应该在编译时加密字符串。我遇到的问题是我无法在构造函数中调用“加密”成员函数,但如果我将加密放在构造函数本身中,它就可以工作。

template<typename I>
class encrypted_string;

template<size_t... I>
class encrypted_string<std::index_sequence<I...>>
{
 private:
  std::array<char, sizeof...(I)> buf;

  constexpr char encrypt(char c) const { return c ^ 0x41; }

 public:
  constexpr encrypted_string(const char* str)
  : buf { (str[I] ^ 0x41)... } { } // Works
  //: buf { this->encrypt(str[I])... } { } // Error
};

#define enc(str) encrypted_string<std::make_index_sequence<sizeof(str)>>(str)

int main()
{
  // Ensures compile time evaluation
  constexpr auto s = enc("Test");

  return 0;
}

我正在使用 'g++ encrypted_string.cpp -std=c++14 -o encrypted_string' 进行编译,我的 gcc 版本是 4.9.2。

我遇到的错误并没有告诉我太多:

encrypted_string.cpp:17:13: note: ‘constexpr encrypted_string<std::integer_sequence<long unsigned int, _Idx ...> >::encrypted_string(const char*) [with long unsigned int ...I = {0ul, 1ul, 2ul, 3ul, 4ul}]’ is not usable as a constexpr function because:
constexpr encrypted_string(const char* str) : buf { this->encrypt(str[I])... } { }

我做错了什么,还是不能在 constexpr 构造函数中调用 constexpr 函数? 根据我对 constexpr 构造函数的理解,这应该是可能的。

【问题讨论】:

  • A constexpr 在编译时被评估,所以我猜调用作为类实例一部分的方法不是正确的有效请求。我不确定,但至少对我来说是有意义的。
  • 在 gcc 5.1 中工作正常
  • C++14 宽松的常量表达式在 gcc >= 5 中实现,参见gcc.gnu.org/projects/cxx1y.html 使用 C++11 规则,构造函数体内可能没有任何代码(只有 typedefs,static断言等,没有潜在的运行时代码)。
  • 使成员函数static或不是成员。
  • 感谢您的回答,我能够通过将加密函数更改为 staticas Orient 指出的那样在 gcc 4.9 上编译它。我更新到 gcc 5.1,现在它可以正常工作,无需任何修改。

标签: c++ constructor c++14 constexpr


【解决方案1】:

根据https://gcc.gnu.org/projects/cxx1y.html,直到 GCC 5 才实现 C++14 constexpr 支持。

因此,GCC 4.9.2,即使使用-std=c++14,也仅支持 C++11 constexprs,它包含一个产生返回值的语句。 MSVC 2015 RC 也有同样的限制。

constexpr even(int n) { return (n & 1) == 0; } // valid c++11/14
constexpr even(int n) { return (n & 1) ? true : false; } // valid c++11/14
constexpr even(int n) { // valid c++14, not valid c++11
    if ((n & 1) == 0)
        return true;
    return false;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 2013-12-24
    相关资源
    最近更新 更多