此constexpr虚拟功能技术是否违反了任何C 11/C 14规则



i前几天正在阅读C 文档,并注意到,尽管字面类型不得具有虚拟成员,但这并不能阻止它们实现实现虚拟成员。或至少这就是我所理解的。

这是我一直在玩的一些代码:

#include <cassert>
// Some forward declarations:
enum class literal_id;
struct literal_base;
struct literal_a;
struct literal_b;
// Now some definitions:
enum class literal_id {
    a, b 
};
struct literal_base {
    virtual literal_id method() const noexcept = 0;
};
struct literal_a : public literal_base {
    constexpr literal_id method() const noexcept final { return literal_id::a; }
    constexpr operator literal_b() const noexcept;
};
struct literal_b : public literal_base {
    constexpr literal_id method() const noexcept final { return literal_id::b; }
    constexpr operator literal_a() const noexcept;
};
constexpr literal_a::operator literal_b() const noexcept { return literal_b(); }
constexpr literal_b::operator literal_a() const noexcept { return literal_a(); }
// Some test methods
literal_id process_literal_base(literal_base const& l) { return l.method(); }
constexpr literal_id process_literal_a(literal_a const& l) { return l.method(); }
constexpr literal_id process_literal_b(literal_b const& l) { return l.method(); }
// Some test variables
constexpr auto a = literal_a();
constexpr auto b = literal_b();
int main() {
    // Compile-time tests, all ok
    static_assert(process_literal_a(b) == literal_id::a, "");
    static_assert(process_literal_b(a) == literal_id::b, "");
    // Runtime tests, all ok
    assert(process_literal_base(a) == literal_id::a);
    assert(process_literal_base(b) == literal_id::b);
    return 0;
}

一些言论:

  • 我有一个带有隐式(且因此琐碎)驱动器的基类literal_base,因为它的子类别都不应该有一个琐碎的破坏者,但它们是字面类型的类型。
  • literal_base具有用于测试的单个method功能,但目的是使其具有尽可能多的纯虚拟函数(非虚拟最终功能也有效)。
  • )。
  • 请注意,即使不是标记virtualmethod覆盖子类中的覆盖也为final。这只是为了使编译器保持沉默,因为这些类应该是叶子(在其继承树中)或没有覆盖功能。(所有这些都与pre-c 11未定义的行为语义有关,以最终实现虚拟函数,而final指定尚不存在。)
  • 创建了process_*功能是为了帮助断言在编译和运行时实现的正确性。
  • 我也无缘无故地演奏了价值语义,一切都很好:)

字面类型的一些相关定义:

... 可能具有以下所有属性的CV合格类类型:

  • (1)有一个微不足道的破坏者。 [[他们有(我的意思是literal_base的子类)]
  • (2)是
    • (2.1)聚合类型, [[不适用]]
    • (2.2)一种至少一个constexpr(可能是模板)构造函数的类型,它不是副本或移动构造函数, [[它具有,但仅仅是因为所有类都没有明确的构造函数;但是很容易实现]
    • (2.3)闭合类型(自C 17) [[[不适用]]
  • (3)对于工会,至少一个非静态数据成员是非易失性文字类型, [[[不适用]]
  • (4)对于非工会,所有非静态数据成员和基类都是非挥发性的字面类型。(因为C 17) [[示例中没有volatile,并且在真实应用程序中都不得使用volatile;另外,literal_base的子类应该是字面类型,因此该规则必须(并且可以)应用]]
  • (5)所有非静态数据成员和基类都是非易失性字面类型的。 [[基本上]]

现在constexpr函数的一些定义:

  • 一定不能是虚拟 [[[没有一个子类具有虚拟函数;所有这些都是最终的,因此他们的位置是知道的,而无需例如vtables]]
  • (...)

我可以承担所有这些吗?我忽略的规范有什么吗?

[dcl.constexpr]中的规则很清楚:

constexpr功能的定义应满足以下要求:
- 它不会是虚拟的(10.3);

literal_a::methodliteral_b::method都是virtual,因为每个literal_base::method均为virtual。因此,它们不能是constexpr.,它们是final并不重要。该程序的形式不佳。

IT 是,允许文字类型具有virtual成员函数。

最新更新