Disclaimer: I cannot judge wheter you really need templates for what you are doing. That would depend on the number of different types that you want your Adddition class template to work with. If you will only use it for int
, then perhaps this will introduce unnecessary complexity. You can always refactor later (this would be the Agile approach).
Having said that, if you want to use templates, the usual convention is to write T
for a template parameter, and to use type
for a nested typedef
inside a class template. Using typename
or class
is a matter of taste, but typename
stresses the fact that builtin types can also be passed as arguments. Note however that with template-template parameters you would need to write
template<template<typename> class U> SomeClass { /* your definition */ };
^^^^^ // <-- NOT typename here
which stresses the fact that only class templates can be passed as arguments.
There are a few other nitpicks that one could mention about your code that would make it fail to compile (missing return type in convert()
and missing semi-colon in class definition):
template <typename T>
class Addition
{
static const std::size_t N = 256; // are you sure that 256 is all you'll ever need?
T num_a;
T num_b;
void convert(T const*, T const*); // by T const*, not T*
public:
Addition(T const&, T const&); // by T const&, not T
}; // <-- make sure to end class definitions with a semi-colon!
template <typename T>
Addition::Addition(T const& a, T const& b)
{
convert(&a, &b);
num_a = a;
num_b = b;
}
template <typename T>
void Addition::convert(T const* a, T const* b) // <-- use T const* if you don't modify the parameters
^^^^ // <-- you forgot the return type
{
int temp_a = a, temp_b = b;
a = char[N], b = char[N]; <-- hardcoded 256 is bad practice, better to keep that in 1 place only
// converting
}
In C++11 you can even use delegating constructors (supported by latest Visual C++ and of course gcc/Clang) and write
template <typename T>
Addition::Addition(T const& a, T const& b)
:
Addition(&a, &b) // delegate to the other constructor
{}
template <typename T>
Addition::Addition(T const* a, T const* b) // <-- use T const* if you don't modify the parameters
{
int temp_a = a, temp_b = b;
a = char[N], b = char[N]; <-- hardcoded 256 is bad practice, better to keep that in 1 place only
// converting
}
Finally, because template definition have to be in headers anyway, you could even write everything inside the class definition like this:
template <typename T>
class Addition
{
static const std::size_t N = 256; // are you sure that 256 is all you'll ever need?
T num_a;
T num_b;
Addition(T const*, T const*) // by T const*, not T*
{
int temp_a = a, temp_b = b;
a = char[N], b = char[N];
// converting
}
public:
Addition(T const&, T const&) // by T const&, not T
:
Addition(&a, &b) // delegate to the other constructor
{}
}; // <-- make sure to end class definitions with a semi-colon!
This saves you from tediously writing both declarations and definitions of all the member functions. For short and sweet classes (which you should strive for anyway) this is the preferred way of writing templates, but for very long definitions you might want to separate the declaration and definition.
Finally, as was explained by @tacp, you really need to use this->a
to disambiguate a class data member from a function parameter. For that reason, people often write data members with a trailing underscore or a m_
prefix.