标签: constexpr

数组声明中的常量表达式

C++ Primer

必须在编译时知道数组维度,这意味着维度必须是常量表达式

另外一点是这样的

unsigned count = 42;           // not a constant expression
constexpr unsigned size = 42;  // a constant expression
Run Code Online (Sandbox Code Playgroud)

我会,然后期望以下声明失败

a[count];                      // Is an error according to Primer
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.编译并运行良好.

还有一点奇怪的是,++count;在数组声明之后也没有引起任何问题.

-std=c++11flag打开的程序g++4.71

这是为什么?

c++ arrays constexpr

4
推荐指数
1
解决办法
310
查看次数

在编译时计算第n个素数

constexpr在我看来,C++ 11的功能,以及模板参数包应该足够强大,可以执行一些相当复杂的计算.我有一个实际应用的一个可能的例子是在编译时计算第n个素数.

我在想办法实现这个计算.如果提出了多个解决方案,那么比较它们可能会很有趣.

为了让你了解我的性能预期:我希望有一些代码可以在合理的桌面硬件上在不到一秒的编译时间内找到第512个素数(即3671).

c++ compile-time template-meta-programming constexpr c++11

4
推荐指数
2
解决办法
3137
查看次数

constexpr功能的规则

以下示例中:

//Case 1
constexpr int doSomethingMore(int x)
{
    return x + 1;
}

//Case 2
constexpr int doSomething(int x)
{
    return ++x;
}


int main()
{}
Run Code Online (Sandbox Code Playgroud)

输出:

prog.cpp:在函数'constexpr int doSomething(int)'中:
prog.cpp:12:1:错误:表达式'++ x'不是常量表达式

为什么案例1被允许但案例2不被允许?

c++ constexpr c++11

4
推荐指数
1
解决办法
453
查看次数

理解左值到右值转换的示例

我很难理解这段代码(C++ 14草案标准[conv.lval]中的一个例子)是如何调用未定义的行为的g(false).为什么constexpr让程序有效?

另外,"不访问y.n" 是什么意思?在两个调用中g()我们都返回n数据成员,为什么最后一行说它不访问它?

struct S { int n; };
auto f() {
    S x { 1 };
    constexpr S y { 2 };
    return [&](bool b) { return (b ? y : x).n; };
}
auto g = f();
int m = g(false); // undefined behavior due to access of x.n outside its
                  // lifetime
int n = g(true);  // OK, does not access y.n
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer lvalue-to-rvalue constexpr c++14

4
推荐指数
1
解决办法
612
查看次数

为什么要在构造函数上使用constexpr?

我理解这constexpr将允许您在编译时将对象用作常量,但是什么时候这将是有益的?我试图更好地理解关键字,但是在构造函数上使用它时,我找不到一个很好的例子来解释它为什么需要它.

下面的两个例子都有用,那么为什么constexpr放在构造函数上呢?

使用constexpr构造函数:

#include <iostream>
using namespace std;

class Rect
{
    public:
        constexpr Rect(int width, int height)
            : mWidth(width), mHeight(height) {}
        constexpr int getArea() const { return mWidth * mHeight; }
    private:
        int mWidth, mHeight;
};

int main(int argc, char* argv[])
{
    constexpr Rect r(8, 2);

    cout << r.getArea() << endl;   //16

    int myArray[r.getArea()];    // OK


    return 0;
}
Run Code Online (Sandbox Code Playgroud)

没有constexpr构造函数:

#include <iostream>
using namespace std;

class Rect
{
    public:
        Rect(int width, int height)
            : mWidth(width), mHeight(height) {}
        constexpr …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr

4
推荐指数
1
解决办法
713
查看次数

构造一个constexpr std :: weak_ptr

根据std::weak_ptr文档,可以构建一个constexpr weak_ptr:

#include <memory>
constexpr weak_ptr<int> foo{};
Run Code Online (Sandbox Code Playgroud)

但是,使用clang尝试这个会产生一个编译错误,抱怨constexpr变量不能有非文字类型' const std::weak_ptr<int>',这是因为weak_ptr<int>有一个用户提供的析构函数.(确实如此,查看libc ++标头)

我的问题是,这是一个libc ++错误,还是constexpr weak_ptr没有意义,并且constexpr默认构造函数是错误的?我可以期待这种情况在未来发挥作用吗?

c++ destructor weak-ptr constexpr c++11

4
推荐指数
1
解决办法
197
查看次数

为什么for循环不是编译时表达式,扩展constexpr允许constexpr函数中的for循环

我写了这样的代码

#include <iostream>
using namespace std;
constexpr int getsum(int to){
    int s = 0;
    for(int i = 0; i < to; i++){
        s += i;
    }
    return s;
}
int main() {
    constexpr int s = getsum(10);
    cout << s << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我知道它的工作原理是因为扩展了constexpr.然而,在这个问题为什么不是一个for-loop-a-compile-time-expression,作者给出了他的代码如下:

#include <iostream>
#include <tuple>
#include <utility>

constexpr auto multiple_return_values()
{
    return std::make_tuple(3, 3.14, "pi");
}

template <typename T>
constexpr void foo(T t)
{
    for (auto i = 0u; i < …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++11 c++14

4
推荐指数
2
解决办法
3823
查看次数

切换constexpr功能

Wiki中找到以下声明:

C++ 11引入了constexpr声明函数的概念; 一个可以在编译时执行的函数.它们的返回值可能由需要常量表达式的操作使用,例如整数模板参数.但是,C++ 11 constexpr函数只能包含一个返回的表达式(以及static_asserts和少量其他声明).

C++ 14放宽了这些限制.Constexpr声明的函数现在可以包含以下内容:条件

  • ...
  • 分支声明ifswitch

那么,实际上是否可以在c ++ 14/c ++ 17中的constexpr函数中进行切换?而且,如果可能的话,那是什么语法?例如,我想要这样的东西:

enum class Terrain : std::uintmax_t {
    ROAD,
    SOIL,
    GRASS,
    MUD,
    SNOW,
};

constexpr float
getStepPrice(Terrain const& terrain)
{
    switch constexpr (terrain)
    {
        case Terrain::ROAD: return 1.0f;
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++14 c++17

4
推荐指数
2
解决办法
6005
查看次数

为什么我不能使用constexpr全局变量来初始化constexpr引用类型?

#include <iostream>
using namespace std;

constexpr int r =100;
int main()
{
    constexpr int &k = r ;
    cout << k << endl;
}
Run Code Online (Sandbox Code Playgroud)

编译此代码会在编译时将"error:binding'const int'引用为类型'int&'丢弃限定符".

c++ constexpr c++11

4
推荐指数
1
解决办法
174
查看次数

如何避免重新键入类型信息以进行聚合初始化?

我有以下示例:

#include <array>

struct A {
    const char* str;
    const char* str2;
};

template<size_t N>
struct As {
    std::array<A,N> elems_;
};


template<class... Args>
As(Args...)->As<sizeof...(Args)>; //<-- NOTE: deduction guide !


constexpr static As as{A{"a","b"}, A{"1","2"}};//<-- 'retyping' A here


int main() {
  return as.elems_.size(); 
}
Run Code Online (Sandbox Code Playgroud)

链接到非工作示例

尽管此代码有效,但我想避免在A汇总列表中对的“重新键入” ,但是如果不加说明,则推导指南将失败:("cannot deduce template arguments for 'As'"我想这很有意义)。解决此问题的一种方法可能是通过手写我需要的任意数量的扣除指南,此后我可以A在每个扣除指南中编写类型(即:针对我需要的每种尺寸的容器进行一次扣除)。

c++ language-lawyer aggregate-initialization constexpr c++17

4
推荐指数
1
解决办法
168
查看次数