首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Constexpr类:继承?

Constexpr类:继承?
EN

Stack Overflow用户
提问于 2014-06-20 18:24:49
回答 1查看 4.2K关注 0票数 3

首先,我和Clang 3.4.1一起工作

我正在编写一个全局变量,它必须作为编译时上下文的占位符(主要作为值模板参数)。为此,我编写了一个名为chameleon (它模仿任何运行时值的行为)的constexpr类:

代码语言:javascript
复制
struct chameleon
{
    template<typename T>
    constexpr operator T() const
    {
        return T{};
    }

    constexpr chameleon() = default;
};

由于转换操作符和构造函数都指定为constexpr,所以我能够在编译时创建该类的实例。例如

代码语言:javascript
复制
template<int foo>
struct bar
{};

using mytype = bar<chameleon{}>;

由于这是可行的,而且我在其他地方使用它,所以我决定编写这样的占位符类型,只从chameleon继承。

代码语言:javascript
复制
template<std::size_t I>
struct placeholder : public chameleon
{
    using chameleon::chameleon;
};

我正在使用C++11,所以我只使用了“新”(C++11有三年时间.)继承构造函数特性。

声明占位符变量时:

代码语言:javascript
复制
constexpr const placeholder<0> _1;

编译器拒绝该代码,说它期望用户定义的默认ctor进行初始化。所以我想,“好吧,继承者不会传播星座,或者诸如此类的东西”。然后,我将the更改为默认的ctor声明:

代码语言:javascript
复制
template<std::size_t I>
struct placeholder : public chameleon
{
    constexpr placeholder() = default;
};

现在编译器说:

错误:默认初始化类型为“const placeholder<0>”的对象需要用户提供的默认构造函数。

如果我将= default更改为手动定义的空构造函数(constexpr placeholder() {}),那么它可以工作,但是构造函数不会被计算为constexpr,而_占位符在编译时上下文中的使用是无效的(常见的is not a constant expression错误)。对于手动调用基ctor也是一样的。

我的问题是:继承和constexpr**constructors?有什么问题?在写** constexpr 类时有没有使用继承的方法?

编辑:我有一个零除法错误,使用手动编写的ctor的代码工作得很好。另一方面,我不明白为什么继承构造函数或默认构造函数声明都不起作用。问题仍然存在。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-20 18:54:56

所以,“好吧,继承者不会传播警察,或者诸如此类的东西”,我是这么想的。

这不是问题;不能继承默认和复制/移动构造函数。如果您没有显式地定义或默认它们,它们将按照通常的规则进行隐式定义。

§12.9 class.inhctor

3对于继承构造函数候选集合中的每个非模板构造函数(不包括没有参数的构造函数或具有单个参数的复制/移动构造函数),除非在出现使用声明的完整类中存在具有相同签名的用户声明构造函数,或者构造函数是该类的默认、复制或移动构造函数,否则构造函数将被隐式声明为相同构造函数特征。..。 5.另一种方法:默认和复制/移动构造函数可以按照12.1和12.8中的规定隐式声明。-end注记

因此,无论是否使用用于继承placeholder的构造函数的声明,chameleon都会有一个默认构造函数,并且这个构造函数将是constexpr

§12.1/5 class.ctor

..。如果用户编写的默认构造函数满足constexpr构造函数(7.1.5)的要求,则隐式定义的默认构造函数是constexpr。..。

您的类提供了一个用户提供的默认构造函数,满足了第7.1.5/4节中对constexpr构造函数的要求。你看到的错误是因为下一部分。

至于为什么必须为const对象提供构造函数定义,让我们看看您的类。

代码语言:javascript
复制
struct chameleon
{
    template<typename T>
    constexpr operator T() const
    {
        return T{};
    }

    constexpr chameleon() = default;
};

这个类是平凡的(9/6)和标准的布局(9/7),因此它是POD (9/10)。默认情况下,POD是未初始化的,因此没有初始化器的const POD将被未初始化,并且是不可变的,这使得它几乎毫无价值(或者至少我无法考虑任何用例)。

通过提供默认构造函数,类不再是POD,并且将被默认初始化。

正如@Casey在评论中指出的那样,这一要求列于第8.5/7节。

如果程序调用const限定类型T的对象的默认初始化,则T应该是具有用户提供的默认构造函数的类类型。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24333458

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档