简体   繁体   English

模板类的专门构造函数

[英]Specialized constructors for a template class

I would like to add to a template class a constructor that builds a specialized object with some initializations. 我想向模板类添加一个构造函数,该构造函数通过一些初始化来构建专用对象。 This is the class I'm working on: 这是我正在从事的课程:

template <typename Tkey, typename Tdata> class t_simple_db{
 private:
  typedef typename std::list<std::pair<Tkey,vector<Tdata>>> t_internal;
  t_internal _db;

 public:
  typedef typename t_internal::const_iterator const_iterator;
  typedef typename t_internal::iterator iterator;

  t_simple_db(){;}
  ~t_simple_db(){;}

  //many methods
};

Now I would like to 现在我想

typedef t_simple_db<string,double> t_simple_db_sd;

and to write a special constructor for it so that in the main I can simply call something like this: 并为此编写一个特殊的构造函数,以便在主体中我可以简单地调用如下代码:

t_simple_db_sd db("this is a string", 100u);

having a correct instantiated and initialized object. 具有正确的实例化和初始化的对象。 I tried to place this in the header after the class declaration: 我试图将其放在类声明之后的标题中:

typedef t_simple_db<string, double> t_simple_db_sd;
template<> t_simple_db<string, double>::t_simple_db(...) {
  ...
}

but I get a bunch of multiple definition errors when I try to compile. 但是当我尝试编译时会遇到很多定义错误。

If this is your class template: 如果这是您的课程模板:

template <typename Tkey, typename Tdata> class t_simple_db{
 private:
  typedef typename std::list<std::pair<Tkey,vector<Tdata>>> t_internal;
  t_internal _db;

 public:
  typedef typename t_internal::const_iterator const_iterator;
  typedef typename t_internal::iterator iterator;

  t_simple_db(){;}
  ~t_simple_db(){;}

  //many methods
};

Then any (implicit) specialization only has a default constructor. 然后,任何(隐式)专业化都只有一个默认构造函数。 You could 你可以

  1. Add a non-default ctor to the (primary) class template 将非默认ctor添加到(主)类模板

     template <typename Tkey, typename Tdata> class t_simple_db{ /* ... */ t_simple_db(){;} t_simple_db(Tkey, std::size_t n) { /*...*/ } ~t_simple_db(){;} //many methods }; 

    In order to define the ctor outside the class definition, put in the header file : 为了在类定义之外定义ctor,将其放在头文件中

     template <typename Tkey, typename Tdata> t_simple_db::t_simple_db() { /* ... */ } 
  2. Partially or explicitly specialize the class template 部分或明确地专门化类模板

     template <> class t_simple_db<std::string, double>{ /* ... */ t_simple_db(std::string, std::size_t n) { /*...*/ } ~t_simple_db(){} //many methods }; 

    In order to define the ctor outside the class definition: Explicitly (= fully) specialized class templates are "ordinary" classes , not templates (you cannot create types from them, they are types with strange names). 为了在类定义之外定义ctor:显式(=完全)专门的类模板是“普通”类 ,而不是模板 (您不能从它们创建类型,它们具有奇怪名称的类型)。 Therefore, the usual rules for functions + ODR apply: preferably put them into the source file (cpp), alternatively as inline or with internal linkage in the header file 因此,适用函数+ ODR的通常规则:最好将其放入源文件(cpp)中,或者以内inline或在头文件中使用内部链接

     // no `template` t_simple_db<std::string, double>::t_simple_db(..) { /*...*/ } // or typedef t_simple_db<string, double> t_simple_db_sd; t_simple_db_sd::t_simple_db(..) { /*...*/ } 

In your pastebin, there's a ctor 在您的pastebin中,有一个ctor

t_simple_db(const string& keys, const size_t& res );

I wouldn't recommend putting this ctor in the primary template: Not all specializations of t_simple_db might use string s as Tkey s. 我不建议将此ctor放在主模板中:并非t_simple_db所有专业化t_simple_db可以将string用作Tkey You can use inheritance to provide an additional ctor only for certain specializations, eg 您可以使用继承仅为某些专业提供额外的ctor,例如

// header file

template <typename Tkey, typename Tdata> class t_simple_db_base{
 public:
  t_simple_db_base(){;}
  ~t_simple_db_base(){;} // possibly virtual

  //many methods
};

template <typename Tkey, typename Tdata>
class t_simple_db : public t_simple_db_base<Tkey, Tdata>{
 public:
  t_simple_db(){;}
  ~t_simple_db(){;}
};

// explicit specialization of `t_simple_db`
template <>
class t_simple_db<std::string, double>
    : public t_simple_db_base<std::string, double>{
 public:
  t_simple_db(){;}
  t_simple_db(const string& keys, const size_t& res);
  ~t_simple_db(){;}
};

typedef t_simple_db<std::string, double> t_simple_db_sd;


// source file

//template <>  <-- not a member function of a class template,
//                 but of an "ordinary class"
t_simple_db_sd::t_simple_db(const string& keys, const size_t& res)
{
    /*...*/
}

The reason why this function must be in the source file is that it is not a template . 此功能必须在源文件中的原因是它不是模板 Ie, it's not a blueprint that the compiler uses to make functions, but it's a complete function itself. 也就是说,这不是编译器用来制作函数的蓝图,而是它本身是一个完整的函数。 Therefore, it needs to follow the One Definition Rule. 因此,它需要遵循一个定义规则。 As opposed to templates and members of class templates, the linker does not merge the definitions. 与模板和类模板的成员相反,链接器不会合并定义。 You can also provide the definition inside the class definition, implicitly making the function inline . 您还可以在类定义内提供定义,从而使函数inline It's possible as well to provide that definition in the header file outside the class definition, if you explicitly mark the function as inline . 如果将函数显式标记为inline ,也可以在类定义之外的头文件中提供该定义。 If the function is inline , it may appear in multiple translation units. 如果该函数是inline ,则它可能以多个翻译单元出现。

It is also possible to declare the ctor for all specializations but only define it for t_simple_db<std::string, double> . 也可以为所有专业声明ctor,但仅为t_simple_db<std::string, double>定义它。 I don't recommend this approach because misusing the ctor for other specializations will only cause a linker error. 我不推荐这种方法,因为将ctor误用于其他专业领域只会导致链接器错误。 Nevertheless, here's how you can do that: 不过,您可以按照以下方式进行操作:

// header file

template <typename Tkey, typename Tdata> class t_simple_db{
 public:
  t_simple_db(){;}
  t_simple_db(const string& keys, const size_t& res );
  ~t_simple_db(){;}

  //many methods
};

typedef t_simple_db<std::string, double> t_simple_db_sd;


// source file
template <>   // <-- this is a member function of a class template,
              //     therefore we need the `template <>`
              //     in this example, t_simple_db_sd is *not* an explicit
              //     specialization
t_simple_db_sd::t_simple_db(const string& keys, const size_t& res)
{
    /*...*/
}

This function isn't a template either, so the same rules apply as for the member function of an explicit specialization / as for normal functions. 此函数也不是模板,因此适用于明确专门化成员函数的规则/适用于普通函数的规则。

There is a way using variadic templates to do something like this: 使用可变参数模板可以执行以下操作:

template< typename T, typename Alloc >
class MyVector
{
 private:
      T* mem;
 public:

     template< Class... Args >
     MyVector( size_t i, Args &&... args )
     {
          mem = Alloc::alloc( i ); // "pseudo" code to allocate the memory
          for( size_t idx = 0; idx < i; ++idx )
          {
             new ( mem + idx )  T( std::forward<Args>(args)... );
          }
     }
 };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM