请考虑以下代码:
#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?
struct A {
int a = 0;
constexpr A() { a = 1; }
};
constexpr bool f() {
constexpr A a;
static_assert(a.a == 1, ""); // L1: OK
return a.a == 1;
}
static_assert(f(), ""); // L2: Error, can not modify A::a in constexpr
Run Code Online (Sandbox Code Playgroud)
如果我删除L2,则此代码编译.如果我添加L2,编译器抱怨"在常量表达式中不允许修改const限定类型的对象'const int'".我不是语言律师,所以我不确定这是否属实.但是,如果是,为什么编译器没有抱怨任何关于L1的东西,因为它也称为A()为constexpr?这是一个铿锵的错误吗?或者我错过了什么?
参考:http://en.cppreference.com/w/cpp/language/constexpr
顺便说一句,如果我改变"constexpr A a;" 到"A a;" (删除constexpr关键字),L1无法编译,这是期望的.但是,编译器不再抱怨L2了.
关于此的在线编译器URL:http://goo.gl/AoTzYx
我试图constexpr通过方法更改对象成员的值但我不明白为什么它不适用于这种特定情况:
#include <iostream>
struct test
{
int m_counter = 0;
constexpr test()
{
m_counter++;
m_counter++;
increment();
increment();
increment();
}
constexpr void increment()
{
m_counter++;
}
constexpr int value() const
{
return m_counter;
}
};
template<int value>
constexpr void check()
{
std::cout << value << std::endl;
}
// constexpr test t; // value = 3, why ?
int main()
{
constexpr test t; // value = 5, ok
check<t.value()>();
}
Run Code Online (Sandbox Code Playgroud)
当我在全局范围内创建对象时,我不明白为什么值为3.msvc和clang在两种情况下都显示5但不是gcc.谁错了?
我的理解是这个(荒谬的)代码无效C++ 14:
class Point {
public:
constexpr double setX(double newX) { return x = newX; }
private:
double x;
};
Run Code Online (Sandbox Code Playgroud)
我想弄清楚C++ 14标准中的哪一部分(仍然正式起草)不允许它.对constexpr功能的限制在7.1.5/2中列出.(抱歉格式错误.我无法弄清楚如何击败降价使其看起来正确.)
constexpr函数的定义应满足以下约束:
- 它不应是虚拟的(10.3);
- 其返回类型应为字面类型;
- 每个参数类型都应是文字类型;
- 它的函数体应为= delete,= default或不包含的复合语句
- asm-definition,
- 一个goto声明,
- 尝试块,或
- 非文字类型或静态或线程存储持续时间的变量的定义,或者不执行初始化的定义.
那里没有任何禁止分配给数据成员的东西.在5.19/2(子弹15)中有这样的禁令(再次出现格式错误,抱歉):
条件表达式e是核心常量表达式,除非根据抽象机器(1.9)的规则评估e将评估以下表达式之一:[...]对象的修改(5.17,5.2.6) ,5.3.2)除非它适用于文字类型的非易失性左值,指的是在e的评估范围内开始生命的非易失性对象;
但我不知道5.19如何适用于7.1.5.有人可以澄清一下吗?