Constexpr类:继承?

时间:2014-06-20 18:24:49

标签: c++ inheritance c++11 constexpr

首先,我正在使用Clang 3.4.1

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

struct chameleon
{
    template<typename T>
    constexpr operator T() const
    {
        return T{};
    }

    constexpr chameleon() = default;
};

由于转换运算符和构造函数都指定为constexpr,因此我能够在编译时创建该类的实例。 For example

template<int foo>
struct bar
{};

using mytype = bar<chameleon{}>;

由于这个工作,我在其他地方使用它,我决定编写这样的占位符类型 只是继承自chameleon

template<std::size_t I>
struct placeholder : public chameleon
{
    using chameleon::chameleon;
};

我使用的是C ++ 11,所以我只使用了&#34; new&#34; (C ++ 11有三年......)继承构造函数。

声明占位符变量时:

constexpr const placeholder<0> _1;

编译器拒绝代码,说它需要用户定义的默认ctor进行初始化。所以&#34;嗯,继承ctors并没有传播constexpr,或类似的东西&#34; 就是我的意思。然后我将使用更改为默认的ctor声明:

template<std::size_t I>
struct placeholder : public chameleon
{
    constexpr placeholder() = default;
};

现在编译器说:

  

错误:const类型的对象的默认初始化&#39; const占位符&lt; 0&gt;&#39;需要用户提供的默认构造函数

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

我的问题是:继承和constexpr构造函数有什么问题?在编写constexpr类时,有没有办法使用继承?

编辑:我有一个被零划分的错误,使用手动编写的ctor的代码完美无缺。另一方面,我不明白为什么继承构造函数或默认构造函数声明都不起作用。问题仍然存在。

1 个答案:

答案 0 :(得分:4)

  

所以“好吧,继承ctors不传播constexpr,或类似的东西”是我的想法

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

§12.9[class.inhctor]

  

3对于继承构造函数的候选集中的每个非模板构造函数,除了没有参数的构造函数或具有单个参数的复制/移动构造函数之外,构造函数隐式声明为相同构造函数特性,除非有一个用户声明的构造函数具有相同的构造函数   完整类中出现 using-declaration 的签名,或者构造函数是该类的默认,复制或移动构造函数。 ...

     

5 [注意:默认和复制/移动构造函数可以隐式声明为12.1和12.8中指定的。 -end note ]

因此,无论使用或不使用继承placeholder构造函数的using声明,chameleon都将隐式定义默认构造函数,此构造函数将为constexpr

§12.1/ 5 [class.ctor]

  

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

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


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

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在comments中指出,此要求列于§8.5/ 7

  

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