标签: constexpr

在编译时使用Constexpr填充数组

我想使用constexpr填充一个枚举数组.阵列的内容遵循某种模式.

我有一个枚举将ASCII字符集分为四类.

enum Type {
    Alphabet,
    Number,
    Symbol,
    Other,
};

constexpr Type table[128] = /* blah blah */;
Run Code Online (Sandbox Code Playgroud)

我想有一个128的数组Type.它们可以是一个结构.数组的索引将对应于ASCII字符,值将是Type每个字符的值.

所以我可以查询这个数组,找出ASCII字符属于哪个类别.就像是

char c = RandomFunction();
if (table[c] == Alphabet) 
    DoSomething();
Run Code Online (Sandbox Code Playgroud)

我想知道如果没有一些冗长的宏观黑客,这是否可行.

目前,我通过执行以下操作来初始化表.

constexpr bool IsAlphabet (char c) {
    return ((c >= 0x41 && c <= 0x5A) ||
            (c >= 0x61 && c <= 0x7A));
}

constexpr bool IsNumber (char c) { /* blah blah */ }

constexpr bool IsSymbol (char c) { /* blah blah */ } …
Run Code Online (Sandbox Code Playgroud)

c++ templates constexpr c++11

20
推荐指数
3
解决办法
1万
查看次数

声明constexpr initializer_list对象是否合法?

作为在讨论这个SO问题时提出的一个问题:

申报对象是否合法,可能是N3471constexpr std::initializer_list?例:

constexpr std::initializer_list<int> my_list{};
Run Code Online (Sandbox Code Playgroud)

为什么我认为它可能不合法:initializer_list必须是字面类型; 但有没有保证它是文字类型?

来自N3485的引文.

[dcl.constexpr]/9:

对象声明中使用的constexpr说明符将对象声明为const.这样的对象应具有文字类型并应初始化.

文字类型要求,[basic.types]/10,子项目类类型:

  • 具有以下所有属性的类类型(第9节):
    • 它有一个简单的析构函数,
    • 非静态数据成员(如果有)的brace-or-equal-initializers中的每个构造函数调用和完全表达式都是一个常量表达式(5.19),
    • 它是一个聚合类型(8.5.1)或者至少有一个constexpr构造函数或构造函数模板,它不是复制或移动构造函数,并且
    • 它的所有非静态数据成员和基类都是非易失性文字类型.

奖励积分;)用于回答if

constexpr std::initializer_list<int> my_list = {1,2,3,4,5};
Run Code Online (Sandbox Code Playgroud)

是合法的(有参考).虽然我认为上述+ [dcl.init.list]/5涵盖了这一点

c++ initializer-list language-lawyer constexpr c++11

20
推荐指数
1
解决办法
6173
查看次数

未定义的是__builtin_ctz(0)还是__builtin_clz(0)?

背景

很长一段时间,gcc一直在提供许多内置的bit-twiddling函数,特别是尾随和前导0位的数量(也用于long unsignedlong long unsigned,有后缀lll):

- 内置功能: int __builtin_clz (unsigned int x)

x从最高有效位开始返回前导0位的数量.如果x为0,则结果未定义.

- 内置功能: int __builtin_ctz (unsigned int x)

x从最低有效位开始返回尾随0位的数量.如果x为0,则结果未定义.

在每一个在线(免责声明:仅64位)编译器,我测试,然而,结果是,无论clz(0)ctz(0)返回底层内建类型,例如位的数目

#include <iostream>
#include <limits>

int main()
{
    // prints 32 32 32 on most systems
    std::cout << std::numeric_limits<unsigned>::digits << " " << __builtin_ctz(0) << " " << __builtin_clz(0);    
}
Run Code Online (Sandbox Code Playgroud)

实例.

尝试过的解决方法

在最新的锵SVN主干std=c++1y模式取得了所有这些功能放宽C++ 14 constexpr,这使得它们的候选在SFINAE表达式以用于围绕3包装函数模板 …

c++ bit-manipulation undefined-behavior constexpr c++14

20
推荐指数
3
解决办法
1万
查看次数

为什么在类中初始化的非整数静态数据成员必须是constexpr?

在类定义中初始化静态整型数据成员可以声明constconstexpr,但在类定义中初始化非整数的静态数据成员必须是constexpr:

class MyClass {
  static const     int   w = 5;          // okay
  static constexpr int   x = 5;          // okay
  static const     float y = 1.5;        // error!
  static constexpr float z = 1.5;        // okay
};
Run Code Online (Sandbox Code Playgroud)

有人知道为什么不允许y的声明吗?标准中将其定为非法的部分是9.4.2/3,但为什么它是非法的?

c++ static-members constexpr c++11

20
推荐指数
1
解决办法
6658
查看次数

为什么主要不能成为constexpr?

当您尝试使用constexpr时,main如下所示:

constexpr int main()
Run Code Online (Sandbox Code Playgroud)

gcc和clang抱怨:

错误:无法声明':: main'为内联

错误:'main'不允许声明为constexpr

让我们看看constexpr函数的要求是什么:

constexpr函数必须满足以下要求:

  • 它不能是虚拟的
  • 它的返回类型必须是LiteralType
  • 它的每个参数必须是文字类型

什么是LiteralType?

文字类型是以下任何一种

  • void(因为c ++ 14)
  • 标量类型
  • 参考类型
  • 一个文字类型的数组

功能主体必须包括什么?

  • 空语句
  • static_assert声明
  • typedef声明和不定义类或枚举的别名声明
  • 使用声明
  • 使用指令
  • 正好一个只包含文字值,constexpr变量和函数的return语句.

以下示例:

constexpr int main() { ; }

constexpr int main() { return 42; }

constexpr int main() {
// main defaults to return 0 
}
Run Code Online (Sandbox Code Playgroud)

似乎符合所有这些要求.还有这个,main是在程序开始之前运行的特殊功能.您可以从main运行constexpr函数,并且为了将constexpr标记为constexpr,它必须在constexpr上下文中运行.

那么为什么main不允许成为constexpr?

c++ program-entry-point language-lawyer constexpr c++11

20
推荐指数
3
解决办法
1510
查看次数

constexpr函数中的编译时或运行时检测

当constexpr在C++ 11中引入时,我很兴奋,但遗憾的是我对其有用性做出了乐观的假设.我假设我们可以在任何地方使用constexpr来捕获文字编译时常量或文字编译时常量的任何constexpr结果,包括这样的事情:

constexpr float MyMin(constexpr float a, constexpr float b) { return a<b?a:b; }
Run Code Online (Sandbox Code Playgroud)

因为仅将函数的返回类型限定为constexpr并不将其使用限制为编译时,并且还必须在运行时可调用,所以我认为这将是确保MyMin只能与编译时计算的常量一起使用的一种方法,这将确保编译器永远不会允许它在运行时执行,让我可以编写另一个更加运行时友好的MyMin版本,理想情况下使用相同名称使用_mm_min_ss内在函数,确保编译器不会生成运行时分支码.不幸的是,函数参数不能是constexpr,所以似乎无法做到这一点,除非这样的事情是可能的:

constexpr float MyMin(float a, float b)
{
#if __IS_COMPILE_TIME__
    return a<b?a:b;
#else
    return _mm_cvtss_f32(_mm_min_ss(_mm_set_ss(a),_mm_set_ss(b)));
#endif
}
Run Code Online (Sandbox Code Playgroud)

我严重怀疑MSVC++有这样的东西,但是我希望GCC或者clang至少有一些东西可以实现它,不管它看起来有多么不优.

当然,我提供的示例非常简单,但是如果你可以运用你的想象力,在很多情况下你可以随意做一些事情,比如在一个你知道只能在编译时执行的函数中广泛使用分支语句,因为如果它在运行时执行,性能会受到影响.

c++ compile-time constexpr c++14 c++17

20
推荐指数
2
解决办法
3456
查看次数

Modern C++:初始化constexpr表

假设我有一个类X,哪个功能需要很多常量表值,比如一个数组A[1024].我有一个f计算其值的重复函数,就像

A[x] = f(A[x - 1]);
Run Code Online (Sandbox Code Playgroud)

假设这A[0]是一个已知常量,因此数组的其余部分也是常量.使用现代C++的功能预先计算这些值的最佳方法是什么,并且没有使用此数组的硬编码值存储文件?我的解决方法是一个const静态虚拟变量:

const bool X::dummy = X::SetupTables();

bool X::SetupTables() {
    A[0] = 1;
    for (size_t i = 1; i <= A.size(); ++i)
        A[i] = f(A[i - 1]);
}
Run Code Online (Sandbox Code Playgroud)

但我相信,这不是最美好的方式.注意:我强调数组相当大,我想避免代码的怪异.

c++ precompile constexpr c++11 c++17

20
推荐指数
2
解决办法
2467
查看次数

在头文件中使用constexpr

我可以在头文件中有这样的定义吗?

 constexpr double PI=3.14;
Run Code Online (Sandbox Code Playgroud)

在包含在几个cpp文件中的头文件中有这个问题吗?

我担心,因为它在标准中说这个constexpr有自己的内存,把它放在头文件中,并在几个cpp文件中添加标题,在内存中生成相同值的多个副本以及其他一些令人讨厌的问题.

我正在使用C++ 11

c++ constexpr c++11

20
推荐指数
3
解决办法
7609
查看次数

返回语句中的C++ constexpr函数

为什么constexpr函数在编译时没有被评估,而是在main函数的return语句中运行时?

它试过了

template<int x>
constexpr int fac() {
    return fac<x - 1>() * x; 
} 

template<>
constexpr int fac<1>() {
    return 1; 
} 

int main() {
    const int x = fac<3>();
    return x;
} 
Run Code Online (Sandbox Code Playgroud)

结果是

main:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], 6
        mov     eax, 6
        pop     rbp
        ret
Run Code Online (Sandbox Code Playgroud)

与gcc 8.2.但是当我在return语句中调用该函数时

template<int x>
constexpr int fac() {
    return fac<x - 1>() * x; 
} 

template<>
constexpr int fac<1>() {
    return 1; 
} 

int main() {
    return fac<3>(); …
Run Code Online (Sandbox Code Playgroud)

c++ gcc clang constexpr

20
推荐指数
2
解决办法
1549
查看次数

为什么0 ==("abcde"+1)不是常量表达式?

为什么下面的代码没有编译?

// source.cpp

int main()
{
   constexpr bool result = (0 == ("abcde"+1));
}
Run Code Online (Sandbox Code Playgroud)

编译命令:

$ g++ -std=c++14 -c source.cpp
Run Code Online (Sandbox Code Playgroud)

输出:

source.cpp: In function ‘int main()’:
source.cpp:4:32: error: ‘((((const char*)"abcde") + 1u) == 0u)’ is not a constant expression
 constexpr bool result = (0 == ("abcde"+1));
                         ~~~^~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

我正在使用gcc6.4.

c++ gcc language-lawyer constexpr c++14

20
推荐指数
1
解决办法
658
查看次数