我想出了这个类:
class Point
{
public:
int X, Y;
mutable int Z;
constexpr Point(int x, int y) :X (x), Y(y), Z(0)
{ }
constexpr int GetX() const
{
// Z++; // Wont compile, but following expression is valid!
return X+Z;
}
int GetY() const
{
Z++;
return Y;
}
void FoolConst() const
{
Z++;
}
};
这里是用法:
template<int S>
void foo()
{
std::cout << S << std::endl;
}
int main()
{
constexpr Point pt(10, 20);
pt.FoolConst();
char arr[pt.GetX()]; // Both compile, but GCC is using extended `new`
foo<pt.GetX()>(); // GCC fails, VC compiles
std::cout << sizeof(arr); // 10 (MSVC), 11 (GCC)
std::cout << pt.GetX(); // 11 (MSVC), 11(GCC)
}
问题:
GetX
使用X Z
作为返回表达式编译得很好(Z不是instexpr)。FoolConst
和GetY
方法的constexpr
对象(pt
) ? main
中GetX
的行为在编译器中是不同的。MSVC可以使用int
作为模板参数进行编译,而GCC(IdeOne)不会编译它。对于一个编译器来说< code>constexpr GetX是真正的< code>constexpr,但是对于另一个编译器来说,如果涉及到< code>X Z就不是了。如果我移除< code> Z并简单地< code >返回X GCC就可以了。
我的问题是非常基本的:如果对象是共识,
它怎么能调用一个非共识方法呢?
答案:
为什么GetX
使用X Y
作为返回表达式编译得很好(Z
不是instexpr
)。
mutable
如何从constexpr对象(pt
)中调用FoolConst
和
methods?在编译器中,
GetX
在main中的行为是不同的。MSVC可以用int作为模板参数编译,而GCC(IdeOne)不会编译它。
海湾合作委员会就在这里。C 14 标准 [基本型限定符]:
—const对象是const T类型的对象或此类对象的不可变子对象。
所以,在你的例子中,Z是非常量,因此不能用在常量表达式中,就像GCC所说的:
error: mutable 'Point::Z' is not usable in a constant expression
常量表达式不能访问可变子对象。这在[expr.const]/2中:
条件表达式< code>e是一个核心常量表达式,除非按照抽象机器(1.9)的规则,对e的求值将计算以下表达式之一:[...]
因此< code>GetX不能在常量表达式中使用,例如作为模板参数< code>foo
在回答您的具体问题时:
编译器不需要检查constexpr函数(包括成员函数)在定义时是否完全有效,只有在使用时才需要检查。它确实需要检查一些事情,比如不使用goto
[dcl.constexpr]/3,但不需要检查定义访问哪些对象。这是因为constexpr函数是否可以在常量表达式中使用取决于其参数的值。
事实上,由于GetX
无条件访问Z
,您的程序严格按照[dcl.constexpr]/5具有未定义的行为:
对于非模板的非默认constexpr函数或非模板的、非默认的、非继承的constexpl构造函数,如果不存在参数值,以致函数或构造函数的调用可能是核心常量表达式(5.19)的求值子表达式,则程序格式错误;无需诊断。
“格式不良;“不需要诊断”是程序行为未定义的另一种说法。
那绝对好;从该对象的非constexpr成员函数的角度来看,声明为constexpr
的对象只是一个const
object。
不幸的是,这两个编译器都是正确的;您的程序在GetX
的定义中有未定义的行为,因此编译器没有一个正确的行为。
问题内容: 我有一类具有各种成员变量的类。有一个构造函数,有getter方法,但没有setter方法。实际上,该对象应该是不变的。 现在我注意到了以下几点:当我使用getter方法获得变量列表时,可以添加新值,依此类推- 可以更改。下次调用此变量时,将返回更改的内容。怎么会这样?我没有再设置它,我只是在做它!使用这种行为是不可能的。那么这里有什么区别? 问题答案: 仅仅因为 对 列表 的引用 是不
我试图创建一个自定义数据类型树。定义如下: 树可以定义为包含一条信息(即,它是一个没有子节点的节点)的叶(由关键字“叶”标识),或包含一条信息的节点(由关键字“节点”标识),再加上树列表–列表中的每个元素表示根在相应子节点上的子树。请注意,根据此定义,树永远不能为空。这意味着树可以是: 叶片数据;或 这是我的代码: 它可以编译,但当我尝试运行时: 而不是预期的输出,我得到以下错误: 我的函数的哪一
我试图在C类中实现一个返回模板参数的constexpr成员函数。代码应该是c 11兼容的。然而,当模板化的类还包含STL容器作为数据成员时,比如STD::vector(const expr成员函数不涉及它),我会遇到编译问题。 以下代码给出了一个最小的示例: 代码使用命令正确编译 g -std=c 14 -O3 快速测试.cpp -o 测试 -Wall clang-STD = c 11-O3 qu
在C 14中,由于<code>constexpr</code>不再是隐式<code>常量</code<,所以<code>constexpr<-code>成员函数是否可以修改类的数据成员:
我很难弄清楚如何使用适当的模板化参数调用setValue函数。在ParameterBase抽象基类中不可能有模板化的参数。非常感谢任何帮助。 附注。我没有使用boost::any的灵活性。
我试图通过一个方法更改对象成员的值,但我不明白为什么它在这种特定情况下不起作用: 当我在全局范围内创建对象时,我不明白为什么值是3。msvc和clang在两种情况下都显示5,但不显示gcc。谁错了?