有条件地构造参数包的默认可构造类

时间:2016-05-12 17:44:09

标签: c++ templates c++14 variadic-templates

我有一个模板类Container,其模板构造函数定义如下:

template<class... Objects>
class Container
{
public:
    template<class... Objs>
    Container(Objs*... objs)
    {
        // initialize all pointers of m_objs to nullptr
        objs_init<Objects...>();

        // initialize the pointers of m_objs corresponding to parameters pack objs...
        objs_init<Objs...>(objs...);
    }

private:
    template<class Obj, class O1, class ...On>
    void objs_init()
    {
        objs_init<Obj>();
        objs_init<O1, On...>();
    }
    template<class Obj, class O1, class ...On>
    void objs_init(Obj* obj, O1* o1, On*... on)
    {
        objs_init<Obj>(obj);
        objs_init<O1, On...>(o1, on...);
    }
    template<class Obj>
    void objs_init(Obj* obj = nullptr)
    {
        std::get<Obj*>(m_objs) = obj;
    }

    std::tuple<Objects*...>     m_objs;
};

以及某些课程ABC,...定义如下:

class A { public: A(bool) {} };
class B { /*trivial default ctor*/ };
class C { public: C(int) {} };

如果我以这种方式创建Container<A,B,C>对象:

    Container<A,B,C> cnt(new A(true), new C(1));

假设模板参数中指定的所有类都不同,Container<>模板构造函数按预期工作,即:

  • m_objs元组的所有指针首先设置为nullptr,然后
  • A*的第一个(C*)和第三个(m_objs)指针分别设置为new A(true)new C(1)返回的值。

现在,我希望Container<>构造函数默认构造每个未初始化的m_objs指针。但我不知道如何实现这一点。

我尝试将以下模板成员函数添加到Container<>

    template<class Obj, class O1, class ...On>
    void objs_ctor()
    {
        objs_ctor<Obj>();
        objs_ctor<O1, On...>();
    }
    template<class Obj>
    void objs_ctor()
    {
        Obj*& obj = std::get<Obj*>(m_objs);
        if (obj == nullptr)
            obj = new Obj;
    }

并在objs_ctor<>构造函数中调用Container<>

        // default-construct unitialized pointers of `m_objs`
        objs_ctor<Objects...>();            

但是,这显然不起作用,因为我实现objs_ctor<>的方式要求为参数包的每个类(我不想要)存在默认构造函数;所以我得到以下编译器错误:

error C2512: 'A' : no appropriate default constructor available

为了使其工作,我还需要检查我尝试自动创建的对象是否是默认构造的。我认为这可以使用std::is_default_constructible<>来实现,但我不知道如何正确使用它。

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

假设。

在构造函数

中添加对objs_ctors<Objects...>();的调用
  template<class... Objs>
     Container(Objs*... objs)
      {
        objs_init<Objects...>();
        objs_init<Objs...>(objs...);
        objs_ctors<Objects...>();
      }

以这种方式定义objs_ctor<>()objs_ctors<>()

  template <typename Obj>
     typename std::enable_if<true == std::is_default_constructible<Obj>::value, void>::type objs_ctor ()
      {
        Obj * & obj = std::get<Obj*>(m_objs);

        if ( obj == nullptr)
           obj = new Obj;
      }

  template <typename Obj>
     typename std::enable_if<false == std::is_default_constructible<Obj>::value, void>::type objs_ctor ()
      { }

  template <typename Obj, typename O1, typename ... On>
     void objs_ctors()
      {
        objs_ctor<Obj>();
        objs_ctors<O1, On...>();
      }

  template <typename Obj>
     void objs_ctors ()
      {
        objs_ctor<Obj>();
      }

请注意:我想你的例子

    Obj*& obj = std::get<Obj*>(m_objs);
    if (obj != nullptr)
        obj = new Obj;

错了。

我认为当objobj时,您的意图是修改(分配)nullptr,所以

    Obj*& obj = std::get<Obj*>(m_objs);
    if (obj == nullptr)
        obj = new Obj;

p.s:抱歉我的英语不好。