Calculator using class templates I've just completed an assignment about class templates in C++. It works fine and produces the correct output. We were given the main function and had to construct and implement the class. I'm wondering if there is a better (more efficient) way to construct and implement this simple calculator class template.    

#include &lt;iostream&gt;
#include &lt;string&gt;

using std::cout;
using std::endl;
using std::string;


template &lt;typename T1, typename T2&gt;
class Calculator{
public:
      Calculator(T1 first, T2 second);    
      Calculator( const Calculator&lt;T1, T2&gt;&amp; otherCalculator);      
      void setValue1(T1 first);
      void setValue2(T2 second);
      T1 add();
      T1 multiply();
 private:
      T1 number1;
      T2 number2;
 };

 template &lt;typename T1, typename T2&gt;
 Calculator&lt;T1, T2&gt;::Calculator(T1 first, T2 second)
      :number1(first), number2(second)
 {}

 template &lt;typename T1, typename T2&gt;
 Calculator&lt;T1, T2&gt;::Calculator(const Calculator&lt;T1, T2&gt;&amp; otherCalculator)
      :number1(otherCalculator.number1), number2(otherCalculator.number2)
 {}

 template &lt;typename T1, typename T2&gt;
 void Calculator&lt;T1, T2&gt;::setValue1(T1 first){
      number1 = first;
 }

 template &lt;typename T1, typename T2&gt;
 void Calculator&lt;T1, T2&gt;::setValue2(T2 second){
      number2 = second;
 }

 template &lt;typename T1, typename T2&gt;
 T1 Calculator&lt;T1, T2&gt;::add(){
      T1 answer = number1 + number2;
      return answer;
 }

template &lt;typename T1, typename T2&gt;
T1 Calculator&lt;T1, T2&gt;::multiply(){
      T1 answer = number1 * number2;
      return answer;
}

int main(){
      Calculator&lt;int,int&gt; simpleCalc(42, 3);
      cout &lt;&lt; "Adding: " &lt;&lt; simpleCalc.add() &lt;&lt; endl;
      cout &lt;&lt; "Multiplying: " &lt;&lt; simpleCalc.multiply() &lt;&lt; endl;
      simpleCalc.setValue1( 7);
      cout &lt;&lt; endl;

      Calculator&lt;int,int&gt; copyCalc( simpleCalc);
      cout &lt;&lt; "Adding: " &lt;&lt; simpleCalc.add() &lt;&lt; endl;
      cout &lt;&lt; "Multiplying: " &lt;&lt; simpleCalc.multiply() &lt;&lt; endl;
      cout &lt;&lt; endl;

      Calculator&lt;float,double&gt; realCalc(1.41421, 2.718281828459045);
      cout &lt;&lt; "Adding: " &lt;&lt; realCalc.add() &lt;&lt; endl;
      cout &lt;&lt; "Multiplying: " &lt;&lt; realCalc.multiply() &lt;&lt; endl;
      cout &lt;&lt; endl;
      return 0;
}
Don't flush where you don't need to.

Flushing is expensive, so don't use std::endl unless you need it.
Nearly always, the shorter '\n' suffices, which can be merged with any bordering string-literal.

Still, that advice seems to be for your teacher, not you ;-)
return 0; is implicit in main if control reaches the closing brace }.
The same is true for C since C99.

This also seems to be one for your teacher.
I see you corrected your formatting since posting on SO.

Still, 6 spaces is unusual. Either use the standard tab-stop (8), or if that's too much for your tastes, 4 is a common choice.

Automatic formatting-tools exist which will do this and much additional formatting for you, which gain importance with the size of the project, especially the number of contributors.
There is no reason to write the member-functions of the template out-of-line.

Even if you later divide your projects in multiple files, and thus have headers and implementation-files, templates are always (with really few exceptions) implemented in the header anyway, due to technical constraints.
There is absolutely no reason to explicitly implement the copy-constructor.
Let the compiler provide a default one.
Since C++11, one can also explicitly default it, preferably at the point of declaration: = default;.

Additional benefit: Doing so re-enables move-ctor and move-assignment.
The 2-argument-ctor should be templated to accept any assignable types and use perfect forwarding:

template &lt;typename T3, typename T4, typename = decltype(T1(std::declval&lt;T3&amp;&amp;&gt;()),
    T2(std::declval&lt;T4&amp;&amp;&gt;()), void())&gt;
Calculator(T3&amp;&amp; a, T4&amp;&amp; b) : number1(std::forward&lt;T3&gt;(a)), number2(std::forward&lt;T4&gt;(b)) {}

The setters should accept any assignable type and use perfect forwarding for optimal performance.

template &lt;typename T3&gt;
auto setValue1(T3&amp;&amp; x) -&gt; decltype(number1 = std::forward&lt;T3&gt;(x), void())
{ number1 = std::forward&lt;T3&gt;(x); }
template &lt;typename T3&gt;
auto setValue2(T3&amp;&amp; x) -&gt; decltype(number2 = std::forward&lt;T3&gt;(x), void());
{ number2 = std::forward&lt;T3&gt;(x); }

add and multiply should use a deduced return-type, and be const.
This transfers to avoiding explicit types in the implementations:


Use decltype(std::declval&lt;T1&amp;&gt;()+std::declval&lt;T2&amp;&gt;()) for C++11.

decltype(std::declval&lt;T1&amp;&gt;()+std::declval&lt;T2&amp;&gt;()) add() const;
decltype(std::declval&lt;T1&amp;&gt;()*std::declval&lt;T2&amp;&gt;()) multiply() const;

Or since C++14, just auto for letting the compiler deduce it.

auto add() const {
    auto answer = number1 + number2;
    return answer;
}

Or shorter:

auto add() const {
    return number1 + number2;
}




Putting it all together:

template &lt;class T1, class T2&gt;
class Calculator {
    T1 number1;
    T2 number2;
public:
    template &lt;class T3, class T4, class = decltype(T1(std::declval&lt;T3&amp;&amp;&gt;()),
        T2(std::declval&lt;T4&amp;&amp;&gt;()), void())&gt;
    Calculator(T3&amp;&amp; a, T4&amp;&amp; b) : number1(std::forward&lt;T3&gt;(a)), number2(std::forward&lt;T4&gt;(b)) {}
    // implicit: copy-ctor, move-ctor, copy-assignment, move-assignment, dtor

    template &lt;class T3&gt;
    auto setValue1(T3&amp;&amp; x) -&gt; decltype(number1 = std::forward&lt;T3&gt;(x), void())
    { number1 = std::forward&lt;T3&gt;(x); }
    template &lt;class T3&gt;
    void setValue2(T3&amp;&amp; x) -&gt; decltype(number2 = std::forward&lt;T3&gt;(x), void());
    { number2 = std::forward&lt;T3&gt;(x); }

    auto add() const { return number1 + number2; }
    auto multiply() const { return number1 * number2; }
};