[英]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
};
然后,任何(隱式)專業化都只有一個默認構造函數。 你可以
將非默認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() { /* ... */ }
部分或明確地專門化類模板
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.