我想向模板类添加一个构造函数,该构造函数通过一些初始化来构建专用对象。这是我正在从事的课程:
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
可能将string
s用作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)
{
/*...*/
}
此函数也不是模板,因此适用于明确专门化成员函数的规则/适用于普通函数的规则。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句