Разъяснение по специализации шаблонной функции - PullRequest
2 голосов
/ 22 ноября 2010

Я хочу создать калькулятор

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

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

Теперь я хочу, чтобы этот Caculator добавил строки, поэтому add ("Tim", "Joe") даст мне "TimJoe".

Могу ли я использовать специализацию шаблонной функции для достижения этого путем внесения необходимых изменений в существующий класс.

Ответы [ 3 ]

4 голосов
/ 22 ноября 2010

Если вы используете std::string, вам вообще не придется иметь дело со специализацией шаблона:

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

Это фактически делает то, что, как вы думаете, делает благодаря «магии» стандартной библиотеки, без необходимости писать другой класс.

Однако я бы изменил ваш шаблонный класс, заставив add() принять параметры на const T&:

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 ) ;
    }
};
3 голосов
/ 22 ноября 2010

Зачем вам это нужно?

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

Этот код выводит "Hello world".Это не оптимально (параметры std::string в функции-члене add принимаются по значению), но для работы не требуется специализация.

РЕДАКТИРОВАТЬ ОК, вам нужна специализация,но вы не можете просто специализировать функцию-член 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затем можно будет добавить int, std::string или все, что вам нужно (так как это функция add, которая является шаблоном, а не сам класс Calculator).

1 голос
/ 22 ноября 2010

это возможно (даже если это не обязательно в этом случае для строки, как уже упоминалось @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");
...