标签: constexpr

什么是C++中的constexpr?

我对一个constexpr概念感到困惑,因为我读过的constexpr是在编译时进行评估,因此它对于性能优化与正常情况相比非常有用const.

constexpr int i = 0;
constexpr int& ri = i;
Run Code Online (Sandbox Code Playgroud)

上面的代码返回一个错误"从'const int'类型的表达式中无效初始化类型'int&'的引用",为什么?

此外,下一个代码有一个错误:

constexpr int i = 0;
constexpr int* ri = &i;
Run Code Online (Sandbox Code Playgroud)

如果我替换了constexpr关键字const,以上所有都正常工作.

c++ const constexpr

17
推荐指数
3
解决办法
2122
查看次数

通过值传递的积分常数,被视为constexpr?

虽然我之前使用过这样的代码,但很明显编译器有足够的信息可以工作,但我真的不明白为什么这会编译:

template <class T, class I>
auto foo(const T& t, I i) {
    return std::get<i>(t);
}

int main()
{
    std::cerr << foo(std::make_tuple(3,4), std::integral_constant<std::size_t, 0>{});
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

实例:http://coliru.stacked-crooked.com/a/fc9cc6b954912bc5.

似乎可以同时使用gcc和clang.的事情是,同时integral_constant具有constexpr转换所存储的整数,constexpr成员函数隐式地把对象本身作为参数,并且因此不能被用在这样的函数constexpr的上下文,除非我们正在呼叫的成员函数的对象本身可以作为被处理constexpr.

这里i是一个传递给的参数foo,因此i绝对不能被视为constexpr.然而,确实如此.一个更简单的例子:

template <class I>
void foo(I i) {
    constexpr std::size_t j = i;
}
Run Code Online (Sandbox Code Playgroud)

这也是编译,只要std::integral_constant<std::size_t, 0>{}传递给foo.

我觉得我错过了一些关于constexpr规则的明显内容.无状态类型或其他类型是否有例外?(或者,也许是两个主要编译器中的编译器错误?这个代码似乎适用于clang 5和gcc 7.2).

编辑:答案已经发布,但我认为这还不够.特别是,鉴于最后的定义foo,为什么:

foo(std::integral_constant<std::size_t, …
Run Code Online (Sandbox Code Playgroud)

c++ templates constexpr c++14

17
推荐指数
2
解决办法
1197
查看次数

std::pair&lt;auto, auto&gt; 返回类型

我在玩autoin std::pair。在下面的代码中,函数f应该返回std::pair依赖于模板参数的类型。

一个工作示例:

例 1

template <unsigned S>
auto f()
{
    if constexpr (S == 1)
        return std::pair{1, 2}; // pair of ints
    else if constexpr (S == 2)
        return std::pair{1.0, 2.0}; // pair of doubles
    else
        return std::pair{0.0f, 0.0f}; // pair of floats
}
Run Code Online (Sandbox Code Playgroud)

这适用于 gcc 9.2、gcc 10.0、clang 9.0 和 clang 10.0。

接下来,std::pair为了清楚起见,我想明确地将返回类型写为 a :

例2

template <unsigned S>
std::pair<auto, auto> f()
{
    if constexpr (S == 1)
        return {1, …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr auto std-pair c++17

17
推荐指数
1
解决办法
1715
查看次数

空的析构函数vs文字析构函数

请考虑以下代码:

#include <iostream>

class Test
{
    public:
        constexpr Test(const int x) : _x(x) {}
        constexpr int get() const {return _x;}
        ~Test() {} // HERE
    protected:
        const int _x;
};

int main()
{
    static constexpr Test test(5);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我删除该行HERE代码编译得很好,但是如果我定义一个空的析构函数,则会导致编译错误,说明Test它是非文字的.

为什么空的析构函数和没有析构函数之间有什么区别呢?

编辑:另一个相关的问题:如果空和文字析构函数不同如何定义受保护的文字析构函数?

c++ destructor user-defined-literals constexpr c++11

16
推荐指数
1
解决办法
2126
查看次数

在类模板中正确初始化静态constexpr数组?

由于标准的措辞,C++中的静态类成员给我带来了一点混乱:

9.4.2静态数据成员 [class.static.data]

在类定义中声明静态数据成员不是定义......

但是,constexpr需要在其声明中初始化(AFAIK,无法从标准中找到引用)(例如,在类定义中).

由于constexpr的限制,我实际上已经忘记了在类之外定义静态成员的必要条件,直到我尝试访问静态constexpr数组.这个相关问题提供了定义数组成员的正确方法,但我对类模板中对此定义的含义感兴趣.

这就是我最终得到的结果:

template<typename T>
class MyClass
{
private:
  static constexpr std::size_t _lut[256] = { /* ... */ };
  T _data;

public:
  static constexpr std::size_t GetValue(std::size_t n) noexcept
  {
    return _lut[n & 255];
  }

  // ...
};

template<typename T>
constexpr std::size_t MyClass<T>::_lut[256];
Run Code Online (Sandbox Code Playgroud)

这是正确的语法吗?特别是在定义中使用模板感觉很尴尬,但GCC似乎正确地将所有内容联系起来.

作为后续问题,是否应该类似地定义非数组静态constexpr成员(模板定义在类外)?

c++ templates static-members constexpr c++11

16
推荐指数
2
解决办法
9255
查看次数

如果函数在类范围内声明,constexpr不工作

我使用的是g ++ 4.8.0,它不包含早期的constexprbug.因此下面的代码工作正常:

constexpr int size() { return 5; }
int array[size()];

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

但是,如果我将变量括在一个classas中static,那么它会给出编译器错误:

struct X {
  constexpr static int size() { return 5; }
  static const int array[size()]; 
};

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

这是错误:

错误:数组'array'的大小不是整数常量表达式

禁止以constexpr这种方式使用还是使用另一个g ++ bug?

c++ compiler-errors g++ constexpr c++11

16
推荐指数
2
解决办法
4830
查看次数

为什么我可以在constexpr函数中调用非constexpr函数?

请考虑以下代码:

#include <stdio.h>

constexpr int f()
{
    return printf("a side effect!\n");
}

int main()
{
    char a[f()];
    printf("%zd\n", sizeof a);
}
Run Code Online (Sandbox Code Playgroud)

我本来期望编译器抱怨printf内部的调用f,因为f应该是constexpr,但printf不是.为什么程序编译和打印15

c++ gcc side-effects constexpr c++11

16
推荐指数
1
解决办法
5240
查看次数

constexpr和static constexpr全局变量之间的区别

在C++ 11标准中,在标题中定义时constexpr,static constexpr全局变量之间有什么区别?更具体地说,当多个翻译单元包含相同的标题时,哪个声明(如果有的话)可以保证在翻译单元中定义相同的变量?

例如,

cexpr.h:

#ifndef CEXPR_H
#define CEXPR_H

constexpr int cint = 1;
static constexpr int scint = 1;

#endif
Run Code Online (Sandbox Code Playgroud)

a.cpp:

#include "cexpr.h"
Run Code Online (Sandbox Code Playgroud)

b.cpp:

#include "cexpr.h"
Run Code Online (Sandbox Code Playgroud)

c++ linkage constexpr c++11

16
推荐指数
2
解决办法
4989
查看次数

C++ 17 constexpr字符串解析

对不起,这将是一个很长的帖子,但我觉得你需要所有的代码来看看发生了什么.


所以,我一直在尝试将编译时字符串转换为数据结构解析器.想象一下像正则表达式这样的东西,其中字符串在编译时被"编译"成数据结构但在运行时执行(只要输入字符串当然是常量).但是我遇到了一个我不太明白错误的问题:

基本上,我的设计是一个2遍解析器:

  • 传递1:确定输入字符串中有多少"操作码"
  • 传递2:返回一个大小由Pass 1确定的数组,并填入"opcodes"

这是事情的样子:

// a class to wrap string constants
class constexpr_string {
public:
    template <size_t N>
    constexpr constexpr_string(const char (&s)[N]) : string_(s), size_(N - 1) {}
public:
    constexpr size_t size() const     { return size_; }
    constexpr size_t capacity() const { return size(); }
    constexpr size_t empty() const    { return size() != 0; }
public:
    constexpr char operator[](size_t n) const { return string_[n]; }
private:
    const char *string_;
    size_t      size_;
};

// would have loved to …
Run Code Online (Sandbox Code Playgroud)

c++ parsing constexpr c++17

16
推荐指数
1
解决办法
1848
查看次数

任何用constexpr string_view替换全局const char []的陷阱吗?

我们的团队正在使用具有10多年历史的C ++代码库,并且最近切换到了C ++ 17编译器。因此,我们正在寻找使代码现代化的方法。在YouTube的一次会议演讲中,我听到了用替换const char*全局字符串的建议constexpr string_view

由于我们的代码中有很多这样的const char*全局字符串常量,因此我想问一下是否需要了解一些陷阱或潜在问题?

c++ constexpr string-view c++17

16
推荐指数
1
解决办法
345
查看次数