标签: constant-expression

类型为double的静态类成员的常量表达式初始值设定项

在C++ 11和C++ 14中,为什么我需要constexpr在以下代码段中:

class Foo {
    static constexpr double X = 0.75;
};
Run Code Online (Sandbox Code Playgroud)

而这个产生编译错误:

class Foo {
    static const double X = 0.75;
};
Run Code Online (Sandbox Code Playgroud)

(更令人惊讶的是)这个编译没有错误?

class Foo {
    static const double X;
};

const double Foo::X = 0.75;
Run Code Online (Sandbox Code Playgroud)

c++ static-members constant-expression c++11 c++14

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

关于常量表达式的困惑

这是本主题的某种后续行动,涉及其中的一小部分.与前一个主题一样,让我们​​考虑一下我们的编译器有和的constexpr函数.现在,让我们直截了当地说.std::initializer_liststd::array

这有效:

#include <array>
#include <initializer_list>

int main()
{
    constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
    constexpr int a0 = a[0];
    constexpr int a1 = a[1];
    constexpr int a2 = a[2];
    constexpr std::initializer_list<int> b = { a0, a1, a2 };

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

这不是:

#include <array>
#include <initializer_list>

int main()
{
    constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
    constexpr std::initializer_list<int> b = { a[0], a[1], a[2] …
Run Code Online (Sandbox Code Playgroud)

c++ compile-time constant-expression constexpr c++11

15
推荐指数
1
解决办法
2418
查看次数

C#编译器或JIT可以优化lambda表达式中的方法调用吗?

我在另一个StackOverflow问题开始(在评论中)的讨论后开始这个问题,我很想知道答案.考虑以下表达式:

var objects = RequestObjects.Where(r => r.RequestDate > ListOfDates.Max());
Run Code Online (Sandbox Code Playgroud)

ListOfDates.Max()在这种情况下,是否有任何(性能)​​优势可以移出Where子句的评估,还是1.编译器或2. JIT优化它?

我相信C#只会在编译时进行常量折叠,并且可以认为ListOfDates.Max()在编译时是不可知的,除非ListOfDates本身在某种程度上是常量.

也许还有另一个编译器(或JIT)优化,确保只评估一次?

c# optimization lambda jit constant-expression

15
推荐指数
1
解决办法
1359
查看次数

为什么placement-new表达式不能是常量表达式?

根据[expr.const]/5.18

表达式 E 是核心常量表达式,除非对 E 的求值遵循抽象机 ([intro.execution]) 的规则,将求值以下其中一项:

  • new 表达式 ([expr.new]),除非所选分配函数是可替换的全局分配函数 ([new.delete.single]、[new.delete.array]),并且分配的存储空间在E;

放置新表达式不是常量表达式。

为了解决这个问题,C++20 添加了std::construct_at. 那么为什么不能将placement-new表达式设为常量表达式呢?

c++ placement-new constant-expression c++20

15
推荐指数
2
解决办法
570
查看次数

为什么lambda表达式在未评估的操作数中不允许,但在常量表达式的未评估部分中允许?

如果我们看看草案C++标准部分5.1.2 Lambda表达式2段说(强调我的未来):

lambda表达式的评估导致prvalue临时(12.2).这个临时对象称为闭包对象.lambda表达式不应出现在未评估的操作数中(第5条).[注意:闭包对象的行为类似于函数对象(20.8).-结束注释]

和部分5.19 常量表达式2段说:

条件表达式是核心常量表达式,除非它涉及以下之一作为潜在评估的子表达式(3.2),但是未评估的逻辑AND(5.14),逻辑OR(5.15)和条件(5.16)操作的子表达式不被视为 [...]

并有以下子弹:

- lambda表达式(5.1.2);

那么为什么lambda表达式不允许在未评估的操作数中,但是在常量表达式的未评估部分中是允许的?

我可以看到,对于未评估的操作数,在几种情况下(decltypetypeid)的类型信息不是很有用,因为每个lambda都有一个唯一的类型.虽然为什么我们想要让它们在未经评估的不断表达的背景下不明确,或许是为了让SFINAE

c++ lambda constant-expression c++11 c++14

14
推荐指数
1
解决办法
6355
查看次数

constexpr中的字节序

我想创建一个constexpr函数来返回系统的字节序,如下所示:

constexpr bool IsBigEndian()
{
    constexpr int32_t one = 1;
    return (reinterpret_cast<const int8_t&>(one) == 0);
}
Run Code Online (Sandbox Code Playgroud)

现在,由于函数将在编译时而不是在实际的目标机器上执行,C++规范给出了什么保证以确保返回正确的结果?

c++ endianness language-lawyer constant-expression

14
推荐指数
1
解决办法
657
查看次数

为什么这个添加被默默地忽略了?

我有以下C代码:

#include <stdint.h>
#include <stdio.h>

int i;
uint64_t a[] = { (uint64_t)&i, (uint64_t)&i + 0x8000000000000000 };

int main() {
    printf("%p %llx %llx\n", &i, a[0], a[1]);
}
Run Code Online (Sandbox Code Playgroud)

如果我使用Microsoft Visual Studio Community 2015编译它(作为C或C++)然后运行它,输出类似于以下内容:

013E9154 13e9154 13e9154
Run Code Online (Sandbox Code Playgroud)

看起来,+ 0x8000000000000000我希望设置高位的代码a[1]已经被默默地忽略了.

但是,如果我移动a内部的初始化main,输出就是我所期望的:

00179154 179154 8000000000179154
Run Code Online (Sandbox Code Playgroud)

有了a全球性,为什么要默默地忽略这个添加?尝试添加是否应该实际设置高位a[1]或是否应该导致编译器错误?

有趣的是,如果+ 0x8000000000000000上面的代码被替换为| 0x8000000000000000,我得到"错误C2099:初始化程序不是常量".

编辑:即使没有强制转换,也会出现类似的问题.编译为x64,以下代码打印相同的值(例如000000013FB8D180)三次:

#include <stdio.h>

int i;
int * a[] = { &i, &i + 0x100000000 };

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

c compiler-errors visual-c++ language-lawyer constant-expression

14
推荐指数
1
解决办法
275
查看次数

在C++ 11之前的"常量表达式"

constexpr关键字是在C++ 11中引入的,因为(我认为)是"常量表达式"的相应概念.但是,这个概念隐含在C++ 98/c ++ 03中,因为数组声明需要一个常量表达式:

// valid:
int a[sizeof(int)];
int b[3+7];
int c[13/4];
const int n = 3;
int d[n];
// invalid:
int m = 4;
int e[m];
Run Code Online (Sandbox Code Playgroud)

还有其他"常量表达式",即可以在编译时评估(和/或必须)的表达式; 一个例子是模板参数.

对于预C++ 11,在C++ 98/03标准或其他地方是否存在以下情况?

  • 需要常量表达式的语法结构的完整列表(例如数组声明和模板实例化)
  • 管理这种常量表达式的规则(可能这只是从上面列表中的项到它们在标准中的定义的映射)

c++ compile-time-constant constant-expression c++03 c++98

13
推荐指数
1
解决办法
1409
查看次数

gcc 和 clang 在表达式是否为常量的问题上存在分歧

对于以下程序:

struct S { int i; };

constexpr S f() { 
  return std::is_constant_evaluated() ? S{1} : S{0}; 
}

int main() {
  S s = f();
  return s.i;
}
Run Code Online (Sandbox Code Playgroud)

gcc 返回 0,clang 返回 1。 demo

我不认为 的评估f是在需要不断评估的上下文中进行的,所以我认为 clang 在这里是错误的。还是反过来?还是两个结果都有效?

c++ language-lawyer constant-expression c++20

13
推荐指数
1
解决办法
281
查看次数

为什么Java常量除以零会产生编译时错误?

可能重复:
1/0是合法的Java表达式吗?

为什么这段代码会编译?

class Compiles {
    public final static int A = 7/0;
    public final static int B = 10*3;

    public static void main(String[] args) {}
}
Run Code Online (Sandbox Code Playgroud)

如果我查看已编译的类文件,我可以看到B已经被评估为30,而A仍然是7/0.

据我所知,JSL是一个除以零的表达式,它不是常数.

参考:JLS 15.28

我的上述陈述是由于这一行:

编译时常量表达式是表示基本类型值的表达式

因此,除以零不会被评估为原始值.

我真的不明白为什么编译器允许这样做呢?为了清楚起见,上面的代码使用"java.lang.ExceptionInInitializerError"崩溃了运行时

在我看来,编译器威胁任何最终的静态变量作为常量并评估它的编译时间.这意味着编译器已经尝试评估A,但由于它是零除以它只是让它通过.没有编译时错误.但这看起来非常奇怪...编译器知道它是零除以它会崩溃运行时但是它不会标记编译错误!

任何人都可以向我解释原因吗?

java constants compile-time-constant jls constant-expression

12
推荐指数
1
解决办法
3753
查看次数