当前位置: 首页 > 知识库问答 >
问题:

Constexpr类C++

傅涵忍
2023-03-14

我试图创建一个在编译时构造然后可以使用的类,当然不需要任何修改它的方法。我对staticconstexpr这两个关键字是新手,所以我可能没有正确使用它们。

下面是我的代码:

#include <array>
#include <iostream>

using namespace std;

template<typename unsigned_integer, unsigned_integer max_n>
class ClassicSieve {
  private:
    static array<bool, max_n+1> prime;
    //unsigned_integer max_n;
  public:
    constexpr ClassicSieve() {
      // 1 is not prime
      prime[1] = false;
      // even numbers
      for(unsigned_integer i = 4; i <= max_n; i+=2) {
        prime[i] = false;
      }
      // all the others
      for (unsigned_integer p = 3; p*p <= max_n; p++) {
        if (prime[p]) {
          for(unsigned_integer j = 2*p; j <= max_n; j+=p) {
            prime[j] = false;
          }
        }
      }
    }

    inline bool is_prime(unsigned_integer n) {
      return prime[n];
    }
};

int main() {
  constexpr auto s = ClassicSieve<unsigned int, 10000000>();
  cout << s.is_prime(2) << endl;
  cout << s.is_prime(3) << endl;
  cout << s.is_prime(4) << endl;
  cout << s.is_prime(5) << endl;
  cout << s.is_prime(6700417) << endl;
}

一旦max_n被修复,就可以在编译时评估所有所需的计算,因此可以肯定地说,就可以执行我正在尝试的操作。方法is_prime只读取data_memberprime而不修改它。

当我编译时,我得到:

note: a constant expression cannot modify an object that is visible outside that expression

引用到构造函数。我看到这是一个问题,但在我的情况下,我将不再修改对象。我怎么告诉编译器呢?

共有1个答案

祁默
2023-03-14

这段代码有很多问题:

  • 您的std::array未初始化,并且之后仅将某些值设置为false;您需要将所有值初始化为true
  • 您希望将is_primeconst
  • 标记为
  • 您试图在编译时分配(并循环)1000万个元素,这超出了大多数编译器的限制(您需要为编译器找到适当的标志以增加该限制)
    • 大多数(全部?)std::array的实现尝试执行堆栈分配,这将占用相当大的

    这里有一个实现可以完成这个任务(我将大小限制为10而不是1000万):

    template<typename unsigned_integer, unsigned_integer max_n>
    class ClassicSieve {
      private:
        static constexpr const std::array<bool, max_n+1> prime = ClassicSieve::init_primes();
        static constexpr auto init_primes()
        {
            std::array<bool, max_n+1> prime{};
            prime.fill(true);
            // 1 is not prime
            prime[1] = false;
            // even numbers
            for(unsigned i = 4; i <= max_n; i+=2) {
                prime[i] = false;
            }
            // all the others
            for (unsigned p = 3; p*p <= max_n; p++) {
                if (prime[p]) {
                    for(unsigned j = 2*p; j <= max_n; j+=p) {
                        prime[j] = false;
                    }
                }
            }
            return prime;
        }
      public:
        bool is_prime(unsigned_integer n) const {
          return prime[n];
        }
    };
    

    (*此代码至少假定一个32位无符号整数)

    用法:

    constexpr auto s = ClassicSieve<unsigned int, 10>();
    std::cout << std::boolalpha << s.is_prime(2) << std::endl; // true
    std::cout << std::boolalpha << s.is_prime(3) << std::endl; // true
    std::cout << std::boolalpha << s.is_prime(4) << std::endl; // false
    std::cout << std::boolalpha << s.is_prime(5) << std::endl; // true
    

 类似资料:
  • constexpr-8cc: Compile-time C Compiler constexpr-8cc is a compile-time C compiler implemented as C++14 constant expressions.This enables you to compile while you compile!This project is a port of 8cc

  • 我有以下示例类<code>Foo</code>和嵌套类<code<Bar</code<,所有内容都是<code>constexpr</code>: 我想测试调用<code>Foo::DoTheThing</code>返回1: 海湾合作委员会和Clang都在这里抱怨,但MSVC没有 GCC表示: 错误: ,或者如果我将< code>Bar的定义移到< code>Foo之外,我可以让GCC和Clang

  • 我有以下C 11代码(简化版): GCC 4.9.1可以很好地编译和链接此代码。另一方面,Clang 3.5.0抱怨未定义的引用: 哪个是对的?这个代码合法吗?我对静态Constexr成员规则的理解(主要基于这个问题)是,只有在获取变量的地址时才需要类外定义。但是我没有将Deriv的地址ed::信息或在任何地方使用对它的引用;我只是按值将它传递给Base构造函数。 我发现了各种变通方法: 使两个构

  • 编译此代码会给出“错误:将'const int'绑定到'int类型的引用

  • C++1z将引入“constexpr if”-一个将根据条件删除其中一个分支的if。似乎合理有用。 但是,没有constexpr关键字就不行吗?我认为在编译过程中,编译器应该知道编译时是否知道条件。如果是的话,即使是最基本的优化级别也应该移除不必要的分支。 例如(参见godbolt:https://godbolt.org/g/ipy5y5): Godbolt explorer显示,即使带有-o0的

  • 为什么 C 编译器可以将函数声明为 constexpr,而 constexpr 不能是 constexpr? 例如:http://melpon.org/wandbox/permlink/AGwniRNRbfmXfj8r 输出: 为什么此行出错: