首先,我正在使用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的代码完美无缺。另一方面,我不明白为什么继承构造函数或默认构造函数声明都不起作用。问题仍然存在。
答案 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
应为具有用户提供的默认构造函数的类类型。