Question

I want to create a calculator

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

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

Now I want to make this Caculator add strings, so add("Tim","Joe") shall give me "TimJoe" .

Can I use template function specialization for achieving this by making necessary changes to the existing class .

Was it helpful?

Solution

Why would you want to ?

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

This code outputs "Hello world". It's not optimal (std::string parameters in the add member function are taken by value), but it does not require a specialization to work.

EDIT OK, you want specialization, but you can't just specialize the add member function because the function is not template itself. You can either specialize the whole class :

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 ;
    }
};

Or make the add member function template and specialize it :

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 ;
}

With the second solution, a single Calculator instance will then be able to add int, std::string or whatever you need (as it's the add function which is template, not the Calculator class itself).

OTHER TIPS

If you use std::string, then you won't have to deal with template specialization at all:

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

This in fact does what you think it does thanks to the "magic" of the standard library, without having to write out another class.

I would, however modify your template class by making add() accept parameters by 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 ) ;
    }
};

it is possible (even though it's not neccessary in this case for string as already mentioned by @icecrime and @In silico)

This is the way you could specialize your member function:

#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);
}

The output is:

a b
3

Notice, that it still behaves as you would expect, so you can not do for example this:

    Calculator<int> cci;
    cout << cci.add("a", "b");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top