C++ class templates: redundancy in non-inline member functions? - c++

I just started learning C++ and am looking at the tutorials online on templates.
The example I'm looking at:
// class templates
#include <iostream>
using namespace std;
template <class T>
class mypair {
T a, b;
public:
mypair (T first, T second)
{a=first; b=second;}
T getmax ();
};
template <class T>
T mypair<T>::getmax ()
{
T retval;
retval = a>b? a : b;
return retval;
}
int main () {
mypair <int> myobject (100, 75);
cout << myobject.getmax();
return 0;
}
What I don't complete understand is the heading for getmax():
template <class T>
T mypair<T>::getmax ()
A few questions:
Is it possible to include fewer or more template parameters in the member function definition than in the template class? So, if mypair actually took in class T and class U, then when you define getmax, is it possible to only pass class T as a template parameter?
If that's not the case, then is it redundant to have class T and mypair<T>? Since you cannot have different template parameters anyway?
Sorry if this isn't completely clear.
Thanks!

When you declare your template class mypair, you are actually declaring three fairly independent templates: a class template for mypair, a function template for mypair::mypar constructor and a function template for mypair::getmax member function. Thise templates are, of course, not completely unrelated, since getmax is a member of mypair, but they still have a significant degree of independence. They are instantiated independently, they can be specialized independently.
For example, you can explicitly specialize mypair::getmax without specializing mypair. This means that there's really no redundancy in what you are talking about. The definition of mypair::getmax is a definition of a [fairly] independent function template. The "basic" definition of that function template has to share the number and the types of its template parameters with class template (so the answer to your "less or more" question is "no"), but nevertheless they are template parameters that belong to function template.
However, you are not required to provide the "basic" definition for mypair::getmax at all. You already declared it in the class, so if you wish, you can omit the "basic" definition completely and proceed to defining the specializations right away
template<> int mypair<int>::getmax() {
// whatever
}
template<> double mypair<double>::getmax() {
// whatever
}

Yes, it's possible to have a different numbers of template parameters in more advanced situations. For now, though, just write it like that.

Related

How do I define methods outside of the declaration for my specialization of a non-type template class?

The title is a mouthful, but basically I wrote something like this:
enum EnumType{ValA, ValB};
template<EnumType> class A {};
template<>
class A<ValA>
{
private:
double param;
public:
A(double param);
};
template<>
A<ValA>::A(double param)
{
// Do Stuff
}
and when I try to compile it I get:
error: template-id 'A<>' for 'A<(EnumType)0u>::A(double)' does not
match any template declaration
Am I doing this wrong?
After searching online for similar cases, I tried to remove template<> (even though I don't understand why this would work), but then I get
multiple definition of 'A<(EnumType)0u>::A(double)'
I guess that I can replace template<> by inline (I tried and it compiles), but that doesn't feel like the proper way to do it (or if it is, I don't understand why).
Can someone explain to me what is wrong with what I wrote, why changing this seems to work, and what's the proper way to do it ?
Can someone explain to me what is wrong with what I wrote, why changing this seems to work, and what's the proper way to do it ?
The standard says:
Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax.
Therefore, in your case you must use:
A<EnumType::ValA>::A(double param)
{
// Do Stuff
}
No template<> at all is just fine. That's because you are actually specializing a (special) member function (the constructor) of an explicitly specialized class template.
See it on coliru.
It would have been different if no explicit specialization was given.
As a minimal working example:
enum EnumType{ValA, ValB};
template<EnumType> class A
{
private:
double param;
public:
A(double param);
};
template<>
A<EnumType::ValA>::A(double)
{
// Do Stuff
}
int main() {
A<EnumType::ValA> a{0.};
}
In this case, template<> is required before the definition of the constructor because you are not defining a specialization of a member function of an already specialized class template.
You missed a semicolon (;) at the the end of class definition.
And the non template member function can be defined this way:
A<ValA>::A(double param) {
// Do Stuff
}
Informally, the template parameter list is only written when necessary, for example, for defining a member function template of a class template, the two template parameter list should all be written
template<class U, class V>
class A{
template <class T>
A();
};
template<class U, class V>
template <class T>
A<U, V>::A() {}
and a empty template parameter list is needed for a explicit specialisation of function template (which, i guess, is the reason why you use so here), informally because it tells the compiler that this is not a function overloading.

C++, partial specialization of 2-argument class template: unable to match function definition to an existing declaration

I'm currently implementing a dataset helper class template storing floating point values (Scalar) in a dynamically sized Eigen::Matrix constructed from a vector of different values types (Element) additionally storing a reference to this input vector. Now i want to partially specialize the constructor in the vector value type remaining a template in the scalar type to be explicitly instantiated.
Unfortunately i'm getting "unable to match function definition to an existing declaration" on VS 2010. The code is as simple as:
template <class Scalar, class Element> struct DataSet
{
DataSet(std::vector<Element> const & source);
// several generic member functions here ...
Eigen::Matrix<Scalar, ... > data;
std::vector<Element> const & source;
};
template<class Scalar>
DataSet<Scalar, SomeClass>::DataSet(std::vector<SomeClass> const & input)
{
// special impl for Element==SomeClass ...
}
SomeClass should be automatically be figured out by the compiler, when done right but i tried all meaningful combinations but still getting:
*.cpp(79) C2244 : unable to match function definition to an existing declaration
see declaration of 'DataSet<Scalar, Element>::DataSet'
I was not able to find a matching example by searching the internet yet. Thanks in advance!
EDIT:
To make it more specific, in my real world case i want to be able to define several partial specializations to the constructor with different types for Element e.g:
template<Scalar>
DataSet<Scalar, FirstClass>::DataSet(std::vector<FirstClass> const & first)
: data()
, source(first)
{
// special impl here ...
}
template<Scalar>
DataSet<Scalar, std::shared_ptr<SecondClass> >::DataSet(std::vector<std::shared_ptr<SecondClass> > const & second)
: data()
, source(second)
{
// special impl here ...
}
Redeclaring/specializing the class completely to a certain typename is not desired. Then there is little use to be a template at all. I want the solution as it is, otherwise there might be other strategies to my problem.
FIN:
Since it looks like not being possible to share the type Element between class template and constructor by only specializing the constructor (which is somehow related to an implicit specialization of the class) i removed the reference source from the class template entirely and copied the needed information into a generic container and implemented the constructors via overloads.
When defining your constructor, you didn't explicitly provide both template arguments for its class. That would need to be revised as follows:
template<typename T_Scalar, typename T_Element>
DataSet<T_Scalar, T_Element> // template args for type
::DataSet(std::vector<T_Element> const &input) // but none for constructor
{
// stuff
}
Tangentially related: Unlike methods, template arguments for classes cannot be deduced from constructor calls. That is: until C++17 comes around! woo!
The next stumbling block you faced is that template specialisations do not 'inherit' members from their primary template. It is somewhat intuitive to assume they would, but it's just not so. Until I find an official rationale, I presume it's because template arguments might make certain members totally inapplicable to a specialisation, rendering implicit 'inheritance' problematic. If so, it would've been decided to require full redeclaration / not judged worthwhile to add arcane syntax to specify which primary 'base' members are 'inherited'... when you can simply use real inheritance to ensure they are.
Anyway, what that means is that to get a partial specialisation, you need to declare the whole thing - in this case, the class and its constructor - before you can specialise that constructor's definition. You hadn't declared these ahead of time, so the compiler rightly complained that it couldn't see a declaration.
// Define specialised class
template<typename T_Scalar>
class DataSet<T_Scalar, SomeClass>
{
public:
// Declare its ctor
DataSet(std::vector<SomeClass> const &);
}
// Implement its ctor
template<typename T_Scalar>
DataSet<T_Scalar, SomeClass> // complete template args
::DataSet(std::vector<SomeClass> const &input)
{
// stuff
}
See my working example of an equivalent template class, showing general vs. specialised instantiations.
To add to your original confusion, which is fair! - note that out-of-line definitions can get very complicated indeed if a template class itself contains a template function, because then you need 2 template clauses, e.g.
template<typename TA, typename TB>
class Widget {
template<typename TC>
void accept_gadget(TC &&gadget);
};
template<typename TA, typename TB>
template<typename TC>
Widget<TA, TB>
::accept_gadget(TC &&gadget)
{
/* ... */
}
Something that will help a lot in many contexts, especially including such out-of-line template definitions, is if the proposal to allow namespace class is accepted in a future version. Very sad this didn't make it into C++17... and very odd that it was ever missing in the 1st place!
According to ยง14.7.3.16:
In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.
Still, you can use std::enable_if to partial-specialize your contructor:
template <class Scalar, class Element> struct DataSet
{
template <class T>
DataSet(std::vector<T> const & input, std::enable_if_t<!std::is_same<T, SomeClass>{}> * = nullptr) {
std::cout << "Element\n";
}
template <class T>
DataSet(std::vector<T> const & input, std::enable_if_t<std::is_same<T, SomeClass>{}> * = nullptr) {
std::cout << "SomeClass\n";
}
};
But this way is restrictive:
all your conditions must be exclusives
you'll have to modify the code of your class for every new class you want to handle.
Instead, I'd advise you to use a template helper structure:
DataSet(std::vector<Element> const & input) {
Helper<Element>::do_it(input);
}
that you can specialize as you want:
template <class Element>
struct Helper {
static void do_it(std::vector<Element> const & input) {
std::cout << "General form with Element\n";
}
};
template<>
struct Helper<SomeClass> {
static void do_it(std::vector<SomeClass> const & input) {
std::cout << "SomeClass\n";
}
};
template<>
struct Helper<SomeOtherClass> {
static void do_it(std::vector<SomeOtherClass> const & input) {
std::cout << "SomeOtherClass\n";
}
};
...

why Specialized template class need forward declaration?

such is the code:
template<typename,int> class Uoo; //without this will result in complie error,why?
template<typename T>
class Uoo<T,1>
{
};
int main(){
return 0;
}
why Specialized template class need forward declaration?
The following code is a specialisation of a template.
template<typename T>
class Uoo<T,1>
{
};
But you haven't said what the unspecialised form is, and the language requires you to do that. So you need to add the prototype:
template<typename,int> class Uoo;
You don't actually need to declare the unspecialised form since an instance of it is never required. So a prototype is sufficient.
It's not actually a forward declaration that you're making. What you are doing is first defining the "pattern" of the templated class and then you're defining a specialized context or version of it. The better question is, if you didn't have a non-specialized case, then what would be the point of the 2nd template parameter?
As declared, template<typename T> class Uoo<T,1> is a partial specialization of template<typename,int> class Uoo; it fixes the int parameter to 1. It cannot be a partial specialization of a template that doesn't exist.
You could make your "real" class template self-sufficient by writing
template<typename T>
class Uoo
{
...
};

difference between member function template of a template class and member function of a template class

CODE 1 :
template <class T>
class cat{
public:
T a;
void show(){
cout << a ;
}
};
CODE 2 :
template <class T>
class dog{
public:
T a;
template <class U> // making show function template
void show(){
cout << a ;
}
};
so cat::show() is a member function of a template class.
and dog::show() is a member function template of a template class.
Questions:
1) is there any difference between class template cat and dog, rather than when I call the member function show, I have to explicitly speciafy U for instance of dog template class?
2) does the compiler handles them the same. for example cat::show() will not be compiled until I use it. and I guess the same thing for dog::show();. so is there anything Im missing here ?
Those two are related only in the same way that the two free functions foo are related here:
void foo() {};
template <typename T>
void foo() {}
While being a member of a template class both will be instantiated on demand for implicit instantiations. On the other hand, if you explicitly instantiate the template class, the non-template function will be generated by the compiler, but the template member function will not.
Aside from that, the usual caveats: template functions will only match exact types, while non-template functions will allow implicit conversions:
template <typename T>
struct tmpl {
void foo( T, T ) {}
template <typename U>
void bar( U, U ) {}
};
tmpl<int> t;
t.foo( 5, 1. ); // fine, will convert 1. from double to int
t.bar( 5, 1. ); // error
And all other differences between templated and not templated functions.
What I really don't understand is why this is confusing you so much. It seems that you are considering the instantiation as the only property of functions, which it is not. What is it that really bothers you? Why do you think a template and non-template functions would be the same?
In particular, I feel that you are wasting too much effort into a detail of implementation. In most cases, whether one or all member functions of a template class are instantiated does not really affect the semantics of your program, if your program needs the member function, then the compiler will generate code for it, if your program does not need it, there is no difference whether it generated the code or not (consider that the linker can remove any symbol, what is the difference of the member function never having been generated or it being removed by the linker?)

Differences between template specialization and overloading for functions?

So, I know that there is a difference between these two tidbits of code:
template <typename T>
T inc(const T& t)
{
return t + 1;
}
template <>
int inc(const int& t)
{
return t + 1;
}
and
template <typename T>
T inc(const T& t)
{
return t + 1;
}
int inc(const int& t)
{
return t + 1;
}
I am confused as to what the functional differences between these two are. Can someone show some situations where these snippits act differently from each other?
I can only think of a few differences - here are some examples that don't necessarily cause harm (i think). I'm omitting definitions to keep it terse
template <typename T> T inc(const T& t);
namespace G { using ::inc; }
template <> int inc(const int& t);
namespace G { void f() { G::inc(10); } } // uses explicit specialization
// --- against ---
template <typename T> T inc(const T& t);
namespace G { using ::inc; }
int inc(const int& t);
namespace G { void f() { G::inc(10); } } // uses template
That is because specializations are not found by name lookup, but by argument matching, so a using declaration will automatically consider a later introduced specialization.
Then, you of course cannot partially specialize function templates. Overloading however accomplishes something very similar by partial ordering (using different types now, to make my point)
template <typename T> void f(T t); // called for non-pointers
template <typename T> void f(T *t); // called for pointers.
int a;
void e() {
f(a); // calls the non-pointer version
f(&a); // calls the pointer version
}
That wouldn't be possible with function template explicit specialization. Another example is when references are involved, which causes template argument deduction to look for an exact match of the types involved (modulo base/derived class relationships and constness):
template<typename T> void f(T const &);
template<> void f(int * const &);
template<typename T> void g(T const &);
void g(int * const &);
int a[5];
void e() {
// calls the primary template, not the explicit specialization
// because `T` is `int[5]`, not `int *`
f(a);
// calls the function, not the template, because the function is an
// exact match too (pointer conversion isn't costly enough), and it's
// preferred.
g(a);
}
I recommend you to always use overloading, because it's richer (allows something like partial specialization would allow), and in addition you can place function in whatever namespace you want (although then it's not strictly overloading anymore). For example, instead of having to specialize std::swap in the std:: namespace, you can place your swap overload in your own namespace and make it callable by ADL.
Whatever you do, never mix specialization and overloading, it will be a hell of a mess like this article points out. The Standard has a lovely paragraph about it
The placement of explicit specialization declarations for function templates, class templates, member functions of class templates, static data members of class templates, member classes of class templates, member class templates of class templates, member function templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, member class templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.
Template specialization is more generic than just overloading. You can specialize things like classes rather than just simple functions. Overloading only applies to functions.
UPDATE: To clarify more per AraK's comment, you are really comparing apples and oranges here. Function overloading is used to introduce the ability to have different functions share a single name, if they have different signatures. Template specialization is used to define a specific code snippet for a specific type parameter. You can't have a template specialization if you don't have a template. If you remove the first piece of code that declares the generic template, you'll receive a compile time error if you try to use template specialization.
So, the goal of template specialization is pretty different from a function overload. They just happen to behave similarly in your example while they are fundamentally different.
If you provide an overload, you are declaring an independent method that happens to have the same name. You are not preventing the template to be used with the specific type parameter. To demonstrate this fact, try:
template <typename T>
T inc(const T& t)
{
return t + 1;
}
int inc(const int& t)
{
return t + 42;
}
#include <iostream>
int main() {
int x = 0;
x = inc<int>(x);
std::cout << "Template: " << x << std::endl; // prints 1.
x = 0;
x = inc(x);
std::cout << "Overload: " << x << std::endl; // prints 42.
}
As you can see, in this example, there are two distinct inc functions for int values: inc(const int&) and inc<int>(const int&). You couldn't expand the generic template using int if you had used template specialization.
One such example:
#include <cstdio>
template <class T>
void foo(T )
{
puts("T");
}
//template <>
void foo(int*)
{
puts("int*");
}
template <class T>
void foo(T*)
{
puts("T*");
}
int main()
{
int* a;
foo(a);
}
It is actually suggested that you use non-template overloads for functions and leave specialization for classes. It is discussed at greater length in Why Not Specialize Function Templates?
AFAIK there is no functional difference. All I can add is that if you have both a template function specialisation and an ordinary function defined then there is no overload ambiguity as the ordinary function is favoured.
Just to elaborate on the first point mentioned by litb in his answer. Specializations are only checked once overload resolution has actually selected a primary template. The result can lead to some surprises where a function is overloaded and has explicit specializations:
template <typename T> void foo (T); // Primary #1
template <> void foo<int*> (int*); // Specialization of #1
template <typename T> void foo (T*); // Primary #2
void bar (int * i)
{
foo(i);
}
When choosing which function to call, the following steps take place:
Name lookup finds both primary templates.
Each template is specialized and overload resolution attempts to select a best function based on conversions between the arguments and parameters.
In thise case, there is no difference in the quality of the conversions.
Partial ordering rules are then used to select the most specialized template. In this case that is the second parimary "foo(T*)".
Only after these steps, when the best function has been selected will explicit specializations of the selected function be considered. (In this case primary #2 has none so none are considered).
The only way to call the above explicit specialization here, is to actually use explicit template arguments in the call:
void bar (int * i)
{
foo<int*> (i); // expliit template argument forces use of primary #1
}
A good rule of thumb is to try to avoid having overloads that are also explicily specialized, as the resulting rules are pretty complex.