我想在模板类中添加一个构造函数,该构造函数构建一个带有一些初始化的专用对象。这是我正在上课的课程:
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;
并为它编写一个特殊的构造函数,以便在main中我可以简单地调用这样的东西:
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(...) {
...
}
但是当我尝试编译时,我得到了一堆多重定义错误。
答案 0 :(得分:1)
如果这是您的班级模板:
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
的所有专精都可以将string
用作Tkey
s。您可以使用继承为某些特殊化提供额外的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)
{
/*...*/
}
此函数也不是模板,因此适用与显式特化的成员函数相同的规则/正常函数。
答案 1 :(得分:0)
使用可变参数模板可以这样做:
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)... );
}
}
};