文字类型成员的编译时评估
Compile time evaluation of literal type members
假设我们有两个文字类型A和B,定义如下。文字类型B可以在编译时从文字类型
A初始化。第三个非文字类型C包含文字类型B作为成员。问题是,如果我们在编译时初始化a并将其传递给C的构造函数,那么b是否也在编译时被初始化?由于C是非文字类型,因此其成员v在编译时不会初始化。但是,b是否发生了部分编译时初始化?如果是这种情况,如果在C内部使用constexpr成员函数(如f),是否会在编译时求值?显然,我们不能在编译时在结构C之外使用这样的函数,因为我们不能将C的对象声明为constexpr。
struct A {
constexpr A(int num): num{num} {}
int num;
};
struct B {
constexpr B(A a): num{a.num} {}
int num;
};
template<typename T>
struct C {
C(A a, std::initializer_list<T> data): b{a}, v{data} {}
constexpr int f() const {
return b.num + 42;
}
B b;
std::vector<T> v;
};
int main() {
constexpr A a {4};
C<int> c {a, {5}};
}
您对f
的声明是非法的,因为它是非文字类的非static
constexpr
成员。GCC 6.1给出以下错误:
error: enclosing class of constexpr non-static member function 'int C::f() const' is not a literal type
note: 'C' is not literal because:
note: 'C' has a non-trivial destructor
因此,询问C
的B
数据成员是否在编译时被评估是没有意义的,因为当它被评估时没有办法观察。
一般来说,除非在编译时需要最终结果,否则对constexpr函数的任何调用都可以,但不必在编译时求值。由于C
的构造函数在编译时不需要它的B
参数,所以它是否希望尽早评估转换或生成代码取决于编译器。
一般来说,我相信你会发现,在任何大于零的优化级别上,编译器都会内联和评估构造函数,只需将4分配给C
实例中的适当位置,并直接调用向量构造函数,如果它不只是内联并展开初始化循环,基本上以如下代码结束:
int main() {
C c = UNINITIALIZED;
c.b.num = 4;
c.v._buffer = operator new(sizeof(int) * _MINIMUM_ELEMENTS);
c.v._capacity = _MINIMUM_ELEMENTS;
c.v._size = 1;
c.v._buffer[0] = 5;
}
唯一的方法是编译代码并让编译器发出它生成的程序集。
相关文章:
- 二叉排序树无法编译
- 在编译时评估函数开销的通用方法
- C++ constexpr语言 - 可以在编译时评估值吗?
- 使用 -O3 编译时的不同评估
- 是在编译时评估的C 文字中的算术操作
- 是否可以在编译时评估使用 std::is_same<> 的此条件?
- 通过指向成员的指针对嵌套访问进行编译时评估期间出现 GCC 错误
- 如何在编译时评估基元模板与类模板
- 编译时间评估函数以计算常数
- 在编译时评估 strlen?
- 概括编译时间和运行时间评估
- C 11:具有对数评估深度的编译时间阵列
- 编译时是否需要短路评估规则
- 是否可以在编译时评估数组
- 使用 #pragma message() 打印编译期间 #define 的完整评估结果
- 在C++中,是否可以在编译时使用模板元编程输出评估值
- C++循环的编译时评估
- 为什么编译器在编译期间不评估 constexpr 函数,当每个信息都给出时?
- 使用clang强制编译时对constexpr进行评估
- 文字类型成员的编译时评估