我认为我想模板函数专门化,但this stackoverflow article让我觉得我应该通过函数重载来实现。但是,我只是没有看到如何实现我想要的目标。
我已经能够通过类模板专业化实现目标,但我不喜欢在模板类和专用类之间有如此多的复制代码的事实。
我所拥有的是一个类,其中包括两个用于对类对象进行排序的键。此外,我想创建一个方法match()
,如果字符串的起始部分匹配,则字符串将返回true(即“aaa”将匹配“aaa:zzz”,因为两个字符串的前三个字符都是' aaa'),但是如果它完全匹配(即1 == 1),则仅仅匹配,短路等。
我使用类专门化工作,如下所示:
template <class KEY2_TYPE>
class policy_key_c
{
public:
policy_key_c (int _key1,
KEY2_TYPE _key2) :
key1(_key1),
key2(_key2)
{};
virtual ~policy_key_c(void) {};
virtual std::string strIdx (void) const {
// combine key1 and key2 into an index to be returned.
}
//
// operator <
//
virtual bool operator< (const policy_key_c &b) const {
return (operator<(&b));
}
virtual bool operator< (const policy_key_c *p) const {
// if the primary key is less then it's less, don't check 2ndary
if (key1 < p->key1) {
return (true);
}
// if not less then it's >=, check if equal, if it's not equal then it
// must be greater
if (!(key1 == p->key1)) {
return (false);
}
// its equal to, so check the secondary key
return (key2 < p->key2);
}
//
// operator ==
//
virtual bool operator== (const policy_key_c &b) const {
return(operator==(&b));
}
virtual bool operator== (const policy_key_c *p) const {
// if the primary key isn't equal, then we're not equal
if ((key1 != p->key1)) {
return (false);
}
// primary key is equal, so now check the secondary key.
return (key2 == p->key2);
}
//
// match
//
virtual bool match (const policy_key_c &b) const {
return(operator==(&b));
}
virtual bool match (const policy_key_c *p) const {
return (operator==(p));
}
protected:
int key1; // The primary key
KEY2_TYPE key2; // The secondary key.
// ... other class data members ....
};
// Now specialize the template for a string as the secondary key
//
template <>
class policy_key_c<std::string>
{
public:
//
// .... all the other functions
//
//
// match
//
virtual bool match (const policy_key_c &b) const {
return(operator==(&b));
}
virtual bool match (const policy_key_c *p) const {
// do a prefix string match rather than a complete match.
return (key2.substr(0, p->key2.lenght()) == p->key2);
}
protected:
int key1; // The primary key
std::string key2; // The secondary key.
// ... other class data members ....
};
我不喜欢这个解决方案,因为复制的代码太多了。唯一不同的是匹配函数。当key2是一个int,short或char匹配行为就像== wherease如果key2是一个std :: string我想让它做一个前缀匹配。
这样做有“更有效”的方法吗?这可以通过匹配函数的函数重载来完成吗?如果它可以超载,我会很感激如何的想法。我已经尝试过多种重载变种并且失败了。
提前致谢。
编辑10/12/10
我开始应用PigBen的答案,并且能够让它解决上述问题。然后我尝试了我的实际代码,并意识到我过度简化了我的问题。我实际上有两个模板参数,但我正在尝试基于一个的专业化。
template <int KEY1_VAL, class KEY2_TYPE> class policy_key_c
这是为了允许typdef,例如:
typedef policy_key_c<1, int> int_policy;
typedef policy_key_c<2, std::string> str_policy;
但我发现功能专业化似乎需要指定所有模板参数。
编辑10/12/10
PigBen的建议解决了所述问题。
后来我意识到我的问题略有不同,有两个模板参数,我试图只专注于一个。这真的改变了这个问题。它看起来像我 我需要做像here这样的事情(类似于James McNellis建议的解决方案)。
答案 0 :(得分:3)
如果唯一表现不同的是单个函数,那么您不必专门化整个类,您可以专门化该函数。我不确定当在类的主体中定义函数时是否有语法来执行此操作,但如果您在外部定义函数,那么您可以这样做:
template <class T>
class X
{
void f();
};
template <class T>
void X<T>::f()
{
// general code
}
template<>
void X<std::string>::f()
{
// specialized code
}
对于多个模板参数
template<int K, typename T> class X;
template<int K, typename T> void friend_func(X<K,T> &);
template<int K, typename T>
class X
{
public:
void class_func();
friend void friend_func<>(X &);
};
template<int K, typename T>
void X<K,T>::class_func()
{
friend_func(*this);
}
template<int K, typename T>
void friend_func(X<K,T> & x)
{
// non specialized version
}
template<int K>
void friend_func(X<K,std::string> & x)
{
// specialized version
}
答案 1 :(得分:2)
如果唯一不同的是match
函数,那么让类使用函数指针调用匹配函数,而不是在类中添加匹配函数(类似于C的qsort
功能)。将两个匹配例程写为独立函数,并为类的每个实例分配一个指向相应匹配函数的指针。诚然,这是解决问题的C-ish方法,但它应该可行。
答案 2 :(得分:1)
您可以将match()
函数模板委托给类模板成员函数。然后你可以专门化类模板:
// primary template for general-purpose matching
template <typename T>
struct match_impl
{
static bool match(const T& x) { return true; }
};
// specialization for std::string matching
template <>
struct match_impl<std::string>
{
static bool match(const std::string& x) { return true; }
};
template <typename T>
bool match(const T& x)
{
return match_impl<T>::match(x);
}