簡體   English   中英

模板類的專門構造函數

[英]Specialized constructors for a template class

我想向模板類添加一個構造函數,該構造函數通過一些初始化來構建專用對象。 這是我正在從事的課程:

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
};

現在我想

typedef t_simple_db<string,double> t_simple_db_sd;

並為此編寫一個特殊的構造函數,以便在主體中我可以簡單地調用如下代碼:

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

具有正確的實例化和初始化的對象。 我試圖將其放在類聲明之后的標題中:

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

但是當我嘗試編譯時會遇到很多定義錯誤。

如果這是您的課程模板:

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
};

然后,任何(隱式)專業化都只有一個默認構造函數。 你可以

  1. 將非默認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 }; 

    為了在類定義之外定義ctor,將其放在頭文件中

     template <typename Tkey, typename Tdata> t_simple_db::t_simple_db() { /* ... */ } 
  2. 部分或明確地專門化類模板

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

    為了在類定義之外定義ctor:顯式(=完全)專門的類模板是“普通”類 ,而不是模板 (您不能從它們創建類型,它們具有奇怪名稱的類型)。 因此,適用函數+ 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(..) { /*...*/ } 

在您的pastebin中,有一個ctor

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

我不建議將此ctor放在主模板中:並非t_simple_db所有專業化t_simple_db可以將string用作Tkey 您可以使用繼承僅為某些專業提供額外的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)
{
    /*...*/
}

此功能必須在源文件中的原因是它不是模板 也就是說,這不是編譯器用來制作函數的藍圖,而是它本身是一個完整的函數。 因此,它需要遵循一個定義規則。 與模板和類模板的成員相反,鏈接器不會合並定義。 您還可以在類定義內提供定義,從而使函數inline 如果將函數顯式標記為inline ,也可以在類定義之外的頭文件中提供該定義。 如果該函數是inline ,則它可能以多個翻譯單元出現。

也可以為所有專業聲明ctor,但僅為t_simple_db<std::string, double>定義它。 我不推薦這種方法,因為將ctor誤用於其他專業領域只會導致鏈接器錯誤。 不過,您可以按照以下方式進行操作:

// 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)
{
    /*...*/
}

此函數也不是模板,因此適用於明確專門化成員函數的規則/適用於普通函數的規則。

使用可變參數模板可以執行以下操作:

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