问题描述
我有类似以下内容
class Base {
public:
explicit Base(int* i) noexcept { type = new int; *type = *i; };
constexpr Base(std::nullptr_t) : type(nullptr) { };
~Base() { cout << "Destroying!" << endl; delete type; };
protected:
int* type;
};
class Derived : public Base {
public:
explicit Derived(int* i) noexcept : Base(i) { };
//constexpr Derived(std::nullptr_t) : type(nullptr) { };
//constexpr Derived(std::nullptr_t) : Base(nullptr) { };
~Derived() { };
};
我想实现一些 constexpr
null派生类的构造函数,但是编译器抱怨这两个选项和我所做的类似测试。
I would like to achieve some constexpr
null constructor for the derived class, but the compiler complains a lot about the two options and similar tests I have done.
当然,代码更复杂,我有点不透明处理程序和析构函数的行为应更为复杂。资源释放总是相同的(不需要多个析构函数,只需要 Base
个)。
Of course the code is more complex, I have an opaque handler and the destructor should behave in a more complex way. The resource free-ing is always the same (no need for multiple destructors, only the Base
one).
我不知道如何实现这一目标,也许我走错了路?有任何想法吗?我希望能够执行以下操作:
I don't know how to achieve this, maybe I am going through a wrong path? Any ideas? I expect to be able to do something like:
Derived a(nullptr);
Derived b(handler1);
Base c (nullptr);
Base d (handler2);
,并且在清理过程中, handler1
和 handler2
以某种方式进行管理。
and, in cleanup, both handler1
and handler2
are managed in the some way.
编辑:
Clang(版本3.4)抱怨:
Clang (version 3.4) complains:
error: constexpr constructor never produces a constant expression [-Winvalid-constexpr]
和gcc(版本4.8 [edit:多个版本,尚未全部检查])没有抱怨使用
And gcc (version 4.8 [edit: multiple versions, haven't checked all]) doesn't complain when using
constexpr Derived(std::nullptr_t) : Base(nullptr) { };
实际上, gcc
似乎在做什么我想实现,但是我对 constexpr
不够了解,无法知道哪个编译器运行正确以及如何解决该问题。
In fact, gcc
seems to do what I wanted to achieve, but I do not understand the constexpr
enough to know which compiler is doing right and how I can amend the problem.
推荐答案
常量表达式的类型必须为文字类型。实际上,文字类型分类单元的全部目的是成为可以成为常量表达的事物。参见[expr.const]:
The type of a constant expression must be a literal type. In fact, the entire purpose of the "literal type" taxon is to "be the thing that can be a constant expression". See [expr.const]:
...
—调用文字类的constexpr构造函数以外的函数,一个constexpr函数,
— an invocation of a function other than a constexpr constructor for a literal class, a constexpr function,
...
因此, constexpr
构造函数只允许您在文字类上生成常量表达式,否则,正如编译器告诉您的那样,它将从不生成常量表达式。
Therefore, a constexpr
constructor only allows you to produce constant expressions on literal classes, and otherwise, as your compiler is telling you, it would "never produce a constant expression".
文字类受到[basic.types]的限制:
A literal class is constrained by [basic.types] in this way:
...
具有以下所有属性的类类型(第9条):
— a class type (Clause 9) that has all of the following properties:
- 它具有琐碎的析构函数,
- 它是聚合类型(8.5.1)或至少具有一个
constexpr
构造函数或非复制或移动构造函数模板,并且 - 其所有非静态数据成员和基类是非易失性文字类型。
- it has a trivial destructor,
- it is an aggregate type (8.5.1) or has at least one
constexpr
constructor or constructor template that is not a copy or move constructor, and - all of its non-static data members and base classes are of non-volatile literal types.
但是,从C ++开始14(尤其是 ), constexpr
构造函数还有另一个不相关的用途:它们允许静态初始化(在[basic.start.init]的意义上):
However, as of C++14 (particularly, as of N3652), constexpr
constructors have another, unrelated use: They permit static initialization (in the sense of [basic.start.init]):
所以回顾一下:在C ++ 14中, constexpr
有两个用途:
So to recap: As of C++14, constexpr
has two uses:
-
C ++ 11解释:常量表达式是与其值相同的表达式(即其评估没有副作用);
constexpr
变量只是其值的占位符,并不打算用于它们的对象标识,通常期望常量表达式可以用它们的(编译时)自由替换。
The C++11 interpretation: a "constant expression" is an expression that is identical to its value (i.e. its evaluation has no side effects);
constexpr
variables are just placeholders for their value and not intended to be used for their object identity, and it is generally expected that constant expressions can be freely replaced with their (compile-time knowable) value.
C ++ 14 constexpr
函数,包括构造函数:这些函数,包括可以在静态初始化阶段调用构造函数,以使用静态存储持续时间对变量进行常量初始化。如果变量是对象,则它们仍然保留其对象标识,可能需要动态销毁,但是它们的初始化发生在任何动态初始化之前,并且不受顺序限制。
The C++14 constexpr
functions, including constructors: These functions, including constructors, may be called in the static initialization phase to constant-initialize variables with static storage duration. If the variables are objects, they still retain their object identity and may need dynamic destruction, but their initialization happens before any dynamic initialization and is not subject to ordering.
这篇关于派生类中用于空初始化构造函数的constexpr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!