C ++ 11模板类中模板类成员的初始化

时间:2015-03-30 15:38:55

标签: templates c++11

我有一堆基于枚举类型的模板类。这是源代码:

    #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

2 个答案:

答案 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