类模板特化与函数重载

2024-03-19

我以为我想要模板函数专门化,但是这篇 stackoverflow 文章 https://stackoverflow.com/questions/2197141/function-template-specialization-importance-and-necessity让我觉得我真的应该通过函数重载来实现。然而,我只是不知道如何实现我想要的。

我已经能够通过类模板专业化来实现目标,但我不喜欢模板类和专业类之间有太多重复的代码。

我所拥有的是一个类,其中包含两个用于对类对象进行排序的键。此外,我想创建一个方法,match()如果字符串的起始部分匹配(即“aaa”将匹配“aaa:zzz”,因为两个字符串的前三个字符都是“aaa”),则 for string 将返回 true,但整数、短整型等只会匹配如果完全匹配(即 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 ....
};

我不喜欢这个解决方案,因为有太多重复的代码。唯一行为不同的是 match 函数。当 key2 是 int、short 或 char 匹配时,其行为类似于 == ,而如果 key2 是 std::string 我希望它进行前缀匹配。

有没有一种“更有效”的方法来做到这一点?这可以通过 match 函数的函数重载来完成吗?如果它可以超载,我将不胜感激关于如何超载的想法。我尝试了几种重载的变体,但都惨遭失败。

提前致谢。


编辑 2010 年 10 月 12 日

我开始应用 PigBen 的答案,并能够让它解决我的问题,如上所述。然后我在实际代码上尝试了它,并意识到我过于简化了我的问题。我实际上有两个模板参数,但我正在尝试基于一个参数进行专业化。

template <int KEY1_VAL, class KEY2_TYPE> class policy_key_c

这是为了允许 typedef,例如:

typedef    policy_key_c<1, int>           int_policy;
typedef    policy_key_c<2, std::string>   str_policy;

但我发现函数专业化似乎希望指定所有模板参数。


编辑 2010 年 10 月 12 日

PigBen 的建议解决了上述问题。

后来我意识到我的问题略有不同,有两个模板参数,而我试图只专注于一个。这确实改变了问题。而且看起来我 需要做类似的事情here https://stackoverflow.com/questions/3768862/c-single-template-specialisation-with-multiple-template-parameters(这类似于詹姆斯·麦克内利斯建议的解决方案)。


如果唯一行为不同的是单个函数,那么您不必专门化整个类,您可以只专门化该函数。我不确定当函数在类体内定义时是否有语法可以执行此操作,但是如果您在外部定义函数,那么您可以这样做:

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
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

类模板特化与函数重载 的相关文章

随机推荐

  • 如何使用 ajax 请求发送 Twitter OAuth 访问令牌?

    我想在使用 OAuth 通过 用 twitter 签名 进行身份验证后加载用户的主页时间线 我正在使用这个库来处理身份验证部分https github com jmathai twitter async https github com j
  • 登录 WordPress 网站时如何显示用户的用户名?

    当用户登录到我的 WordPress 网站时 我希望我的网站标题显示 登录身份 我不知道如何回显当前用户的用户名 这是我得到的代码
  • 改变python shell的背景颜色

    例如 是否可以将 Python Shell 的背景颜色从白色更改为黑色 我确实找到了如何更改文本颜色 但不知道如何更改背景颜色 我是在Windows下运行的 有什么建议么 如果您指的是 IDLE 我通过此链接执行了这个简单的步骤 适用于 u
  • 使用列表理解在列表元素前面添加前缀

    有一个这样的列表 foo spam bar 使用列表理解是否可以获取此列表作为结果 foo ok foo spam ok spam bar ok bar In 67 alist foo spam bar In 70 prefix elt f
  • 如何使用 JavaScript 打开新选项卡/窗口?

    客观的 我想在新选项卡 窗口中打开 URLEXACT与 target blank 相同的方式 Code 我正在使用触发以下 JavaScript 的 PHP 条件 我的问题 window open 是不一样作为 target blank 超
  • 为什么 Java 源文件要进入目录结构?

    假设我正在创建一个包含以下类的 Java 项目 com bharani ClassOne com bharani ClassTwo com bharani helper HelperOne com bharani helper suppor
  • 如何从泽西岛 1.0 迁移到泽西岛 2.0?

    我正在尝试升级到 Jersey 2 0 但遇到了很多麻烦 因为 Jersey 的 groupIds 和artifactIds 已完全更改 并且我在 中找不到迁移计划泽西岛文档 https jersey java net nonav docu
  • Google Play 商店的 RSS 源

    Apple 应用程序商店为您提供 RSS 源 以便将提交到应用程序商店的最新应用程序发送到您最喜欢的源阅读器中 我想知道 google play 商店是否也有 RSS feed 可以让你做同样的事情 Thanks 不 他们不提供任何供第三方
  • 您能否提供一些与在项目中使用的人工智能相关的主题想法? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • scala slick 一对多集合

    我有一个数据库 其中包含具有一对多注册关系的活动 目标是获取所有活动及其注册列表 通过创建带有注册的活动的笛卡尔积 获取该数据所需的所有数据都已存在 但我似乎找不到一个好的方法来将它正确地放入 scala 集合中 让我们输入 Seq Act
  • 如何为来自react js中的api的动态表单字段设置常规onchange?

    我正在使用 React 中的表单 我面临的挑战是每当我为输入字段设置 onchange 处理程序时 它都会更改我拥有的所有输入字段的值 表单输入字段已映射并且来自 api 我想要的是一个通用的更改处理程序来管理所有输入字段 import R
  • Spring boot中如何配置gson?

    Spring Boot 2 在application yml中 http converters preferred json mapper gson 现在我用自定义设置编写类Gson public class GsonUtil public
  • 在 QML 中获取 $HOME 和/或用户名

    我需要知道如何获取用户的用户名和 或主目录 我用 google 搜索了一段时间 但只能找到 C 或 BASH 的变量 如何获取用户名或主目录 我正在用 QML 写作 这就是我的实现方式 Qml环境变量 h ifndef QMLENVIRON
  • C#5 ReadAsync 和迭代器

    我正在尝试将下面的类转换为延迟返回文件 public class ObservableFile2 IObservable
  • java.lang.IllegalArgumentException:端口超出范围:67001

    我在运行脚本时遇到以下错误 该脚本正在尝试调用 Web 服务 并且成功调用了 Web 服务 最后 它也打印了成功的消息 只是在中间抛出了一些带有 LOG UTILS 的错误 请大家看看并提出建议 java lang IllegalArgum
  • 在react.js中渲染新元素onClick

    我是反应新手 正在尝试在单击时渲染一个新元素 var LoginButton React createClass clickHandle function this rememberMe active localforage getItem
  • NextJS 公共环境变量不适用于 Azure 应用服务

    I have a NEXT PUBLIC environment variable in my NextJS application It has been set in my env local file and working corr
  • 如何检查文件是否为空

    我有一个文本文件 如何检查是否为空 gt gt gt import os gt gt gt os stat file st size 0 True
  • 如何使用 Room 预封装的数据库回调?

    版本 2 3 0 alpha03 Room 有一个prepackagedDatabaseCallback它说 This callback will be invoked after the pre package DB is copied
  • 类模板特化与函数重载

    我以为我想要模板函数专门化 但是这篇 stackoverflow 文章 https stackoverflow com questions 2197141 function template specialization importanc