【问题标题】:Clarification on template function specialization澄清模板功能专业化
【发布时间】:2010-11-22 10:26:36
【问题描述】:

我想创建一个计算器

template < typename T >
class Calculator
{
    public :
    Calculator ( void );
    ~Calculator ( void );

    T add(T a, T b)
    {
       return ( a + b ) ;
    }
};

现在我想让这个 Caculator 添加字符串,所以 add("Tim","Joe") 应该给我 "TimJoe"。

我可以通过对现有类进行必要的更改来使用模板函数专业化来实现这一点吗?

【问题讨论】:

    标签: c++ templates template-specialization function-templates


    【解决方案1】:

    如果您使用std::string,那么您根本不需要处理模板专业化:

    Calculator<std::string> calc;
    std::string result = calc.add("Tim", "Joe");
    // result contains "TimJoe"
    

    由于标准库的“魔力”,这实际上可以实现您认为的功能,而无需编写另一个类。

    不过,我会修改您的模板类,让add() 接受const T&amp; 的参数:

    template < typename T >
    class Calculator
    {
    public :
        Calculator() {};
        ~Calculator() {};
    
        // Note that we're taking in parameters by const T&
        // to avoid copies if instances of T are large.
        T add(const T& a, const T& b)
        {
            return ( a + b ) ;
        }
    };
    

    【讨论】:

      【解决方案2】:

      你为什么想要?

      Calculator<std::string> a;
      std::cout << a.add("Hello", " world") << std::endl;
      

      此代码输出“Hello world”。它不是最优的(add 成员函数中的std::string 参数按值取值),但它不需要专门化即可工作。

      编辑 好的,你想要特化,但你不能只特化 add 成员函数,因为该函数本身不是模板。你可以专攻整个班级:

      template<>
      class Calculator<std::string>
      {
      public :
          Calculator() {}
          ~Calculator() {}
      
          std::string add(const std::string &a, const std::string &b)
          {
              // Do std::string specific stuff
              return a + b ;
          }
      };
      

      或制作add 成员函数模板并对其进行专门化:

      class Calculator
      {
      public :
          Calculator () {}
          ~Calculator () {}
      
          template<class T>
          T add(T a, T b)
          {
             return a + b;
          }
      };
      
      template<>
      std::string Calculator::add<std::string>(std::string a, std::string b)
      {
          // Do std::string specific stuff
          return a + b ;
      }
      

      使用第二种解决方案,单个 Calculator 实例将能够添加 intstd::string 或您需要的任何内容(因为它是模板的 add 函数,而不是 Calculator 类本身)。

      【讨论】:

      • @silico,@icecrime,通过使用 STL,我可以做到;但我想使用模板专业化
      • @Sujay Ghosh:为什么需要模板专业化?使用std::string 比创建Calculator&lt;T&gt; 的新专业化工作要少得多。
      • 我认为第二种方案是更好的设计。如果有一天我想添加一个自定义类,而不是任何 PODS,这将解决我的问题。
      【解决方案3】:

      这是可能的(尽管在这种情况下对于@icecrime 和@In silico 已经提到的字符串不是必需的)

      这是你可以专门化你的成员函数的方式:

      #include <iostream>
      #include <string>
      
      using namespace std;
      
      template < typename T >
      class Calculator
      {
          public :
          Calculator () {}
          ~Calculator () {}
      
          T add(const T& a, const T& b);
      };
      
      template <typename T>
      T Calculator<T>::add(const T& a, const T& b)
      {
          return (a + b);
      }
      
      template <>
      string Calculator<string>::add(const string& a, const string& b)
      {
          return (a + " " + b);
      }
      
      int main()
      {
          Calculator<string> ccs;
          cout << ccs.add("a", "b") << endl;
      
          Calculator<int> cci;
          cout << cci.add(1, 2);
      }
      

      输出是:

      a b
      3
      

      请注意,它的行为仍然与您预期的一样,因此您不能这样做:

          Calculator<int> cci;
          cout << cci.add("a", "b");
      

      【讨论】:

      • 此代码无法编译。- LNK1169:找到一个或多个多重定义的符号
      • 你这边一定有问题。它适用于我而不会抱怨 g++ -ansi -pedantic -Wall -Wextra 并且它也适用于键盘(打开了 IIRC 相同的标志)参见codepad.org/ZS2QJQQV
      猜你喜欢
      • 2020-06-26
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      • 2010-10-19
      • 2020-07-18
      • 2011-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多