我有一堆基于枚举类型的模板类。这是源代码:
#include <iostream>
// An enum type
enum class ENUMR : unsigned char {
SYSTEM1,
SYSTEM2,
UNKNOWN
};
// template class; will later be specialized based on ENUMR enumerators
template<ENUMR S>
class System
{};
// specialized System class, for enumerator SYSTEM1
template<>
class System<ENUMR::SYSTEM1>
{
private:
static constexpr char identifier { 'G' };
};
// An observation class recorded from a certain System instance
template<ENUMR Sys,short int Freq>
class Obs {
public:
Obs():
m_system {System<Sys> {} }, // does not work
m_frequency {Freq}
{};
//{
// m_system = System<Sys> {}; // works
//}
private:
System<Sys> m_system;
short int m_frequency;
};
// dummy code to test the template classes
int main ()
{
System<ENUMR::SYSTEM1> s1;
System<ENUMR::UNKNOWN> s2;
System<ENUMR::SYSTEM1> s3 (System<ENUMR::SYSTEM1>);
Obs<ENUMR::SYSTEM1, 1> obs;
std::cout <<"\n";
return 0;
}
当Obs::m_system
执行时,成员(模板)变量m_system {System<Sys> {} }
的初始化会产生编译时错误。但是,当相同的变量初始化为m_system = System<Sys> {};
时,源代码将被编译(上面的源代码中的相应行被注释)。
这是否意味着赋值运算符有效,但复制构造函数失败了?如果是这样,为什么?
根据{{1}}编译时,我收到以下错误消息:
gcc version 4.8.3
答案 0 :(得分:1)
如果你改变了
m_system{ System<Sys>{} },
m_frequency{ Freq }
到
m_system( System<Sys>{} ),
m_frequency( Freq )
它会编译。但请注意,第一个初始化程序创建一个默认的构造临时,然后使用复制构造函数初始化该成员。由于您希望m_system
是默认构造的,因此可以省略该初始化程序。
答案 1 :(得分:0)
System<ENUMR::SYSTEM1>
是aggregate,因此mem-initializer m_system { System<Sys>{} }
执行聚合初始化。由于System<ENUMR::SYSTEM1>
没有相应的成员 - 实际上它根本没有成员 - 对于相应的初始化程序System<Sys>{}
,您会得到错误,表明初始化程序太多。
如果System<ENUMR::SYSTEM1>
不是聚合,则该mem-initializer的效果将是从同一类型的值初始化临时值中直接列表初始化m_system
。由于移动/复制构造函数是默认的,因此可以通过使用空括号初始值设定项m_system
直接初始值m_system {}
来实现聚合和非聚合情况的等效效果:{{1}}。 (DEMO)