C++ Template int and strings - c++

#include <string>
#include <iostream>
using namespace std;
template <class T>
class Tyler{
T first, second;
public:
Tyler(T a, T b)
{
first = a;
second = b;
}
int larger();
string larger();
};
template <class T>
int Tyler<int>::larger()
{
cout << "int larger" <<endl;
return(first>second?first:second);
}
template <class T>
string Tyler<string>::larger()
{
cout << "string larger" <<endl;
if(first.compare(second) > 0)
return(first);
return(second);
}
int main()
{
Tyler<int> tobj(7,77);
Tyler<string> tstr("Seven", "test");
cout << tobj.larger() <<endl;
cout << tstr.larger() <<endl;
}
I am learning C++ (templates in particular) and trying to understand. What if I wanted to create the two functions below and the "larger" function will perform different depending on which datatype is specified in the class instantiated in main. I have only seen examples that use int and float.

First, you appear to be trying to specialize the function, so your declarations are not right. You should have this declaration.
T larger();
You want each Tyler object to have only a single larger function, that does different things depending on T. Next, the definitions:
int Tyler<int>::larger()
Here, you're creating a template specialization. It's a template function (well, sort of), so it does need the template bit atop it, but this specialization requires no template parameters, so...
template<>
int Tyler<int>::larger()
Why is that useful? Well, because sometimes a specialization can have template parameters...
template<class T, class Allocator>
vector<T,Allocator> Tyler< vector<T,Allocator> >::larger()

Related

C++ Template Specialization / Partial and Full

I was trying to understand Template Partial and Full Specialization and have this below code:
#include <iostream>
using namespace std;
//Template in C++is a feature. We write code once and use it for any data type including user defined data types.
//What if we want a different code for a particular data type - Template Specialization
template <class T, class Y>
void fun(T a, Y b)
{
cout << "The main template fun(): " << a << " " << b << endl;
}
//If a specialized version is present, compiler first checks with the specialized version and then the main template.
//Compiler first checks with the most specialized version by matching the passed parameter with the data type(s) specified in a specialized version.
template<>
void fun(const char* a, const char* b)
{
cout << "Specialized Template for int type: " << a << " " << b << endl;
}
//Partial specialization allows to specialize only some arguments of a class template, as opposed to explicit full
template<class T>
void fun(T a, int b)
{
cout << "Partial Template specialization for int type: " << a << " " << b << endl;
}
int main()
{
fun<int, int>('a', 10);
fun< const char*, const char*>("Hello", "Morning");
fun<float, float>(10.14, 19.89);
}
Note that in main I am specifying the data types and below is the output:
The main template fun(): 97 10
Specialized Template for int type: Hello Morning
The main template fun(): 10.14 19.89
But when I execute the main code below way:
int main()
{
fun('a', 10);
fun("Hello", "Morning");
fun(10.14, 19.89);
}
This is the output I get:
Partial Template specialization for int type: a 10
Specialized Template for int type: Hello Morning
The main template fun(): 10.14 19.89
So what does the actual C++ Template Partial / Full specialization states - do we need to specify the data types in template argument to invoke - also in many websites I have seen following signature for Partial specialization:
template<class Y, const char*>
void fun(Y a, const char* b)
Rather than
template<class Y>
void fun(Y a, const char* b)
Similarly for full specialization - what is the exact way to write and call Partial / Full template specialized function / class?
The comments cover the general principles, but there are specific questions here worth answering. First, a lemma: the template parameters of a function template need not be related to its parameter types:
template<class T>
T make_1() {return T(1);}
auto v=make_1<std::vector<std::string>>(); // {""}
template<class T,class U>
void f(std::conditional_t<sizeof(T)<sizeof(U),int,long> i);
This is why your “partial specialization” is not a candidate for fun<int, int>(…). The template arguments aren’t just instructions for how to build the parameter list one by one, but rather must match the actual template parameters for the function template in question. There’s only one of those, so they don’t match. True partial specializations still use the primary template’s template parameter list; they just match against certain patterns in the list of arguments for it.
Meanwhile,
template<class Y, const char*>
void fun(Y a, const char* b)
is valid but doesn’t mean what you think for the same reason: const char* in the template parameter list introduces an unnamed (non-type) template parameter of type const char*, so that you’d have to use it like
char global;
void g() {fun<char,&global>('a',"foo");}
(with no deduction for Y!), only to have that &global ignored entirely,

Why these C++ cases instantiate different templates

I am trying to write some functionality where I need to save different functions and later extract their arguments' types. So I'm using the function signature as template parameter. But I get somewhat unexpected results.
Here's the code:
#include <functional>
#include <iostream>
template <class T>
struct foo
{
foo()
{
std::cout << "class T" << std::endl;
}
};
template <class Ret, class Arg>
struct foo<Ret(Arg)>
{
foo()
{
std::cout << "Ret(Arg)" << std::endl;
}
};
template <class T>
void save(std::function<T>)
{
new foo<T>();
}
int main(int argc, char* argv[])
{
std::function<void(void)> someFoo;
save(someFoo);
return 0;
}
So if the variable someFoo is a function with type void(void), it instantiates the first template, foo<T>. But if I change it to void(int), than I get the desired specialized template instantiated. Why is that?
In C++, having a void argument is actually the same as having no argument at all (unlike in C, by the way). So it would match a specialization for Ret(), but it can't match a specialization for Ret(Arg).
void(void) is the exact same as void() - the second void is optional and makes no difference.
That's why the first template with no parameters is used.

why is it necessary to include template parameter before every function even if we are not using diduced type in the function?

Why are we suppose to use template parameters at front of every function even if we are not using deduced template parameters in the function. As we can see that i am not using template parameter _T in printP() function (around 30) then why it is required to include template syntax at front of this function.
NOTE: This is very simplified version of my big class, and it might look silly because it is very small but, consider a situation where you are using template for only few [2-3] function of your class but you are bound to type (even copy past) this lengthy template syntax at front of every function but i am asking why??.
Is there any way to get of this
#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;
template<typename _T>
class Thing{
int _p;
_T _k;
public:
Thing(int p, _T k):_p(p),_k(k){}
void printK();
void printP();
};
template<typename _T>
void Thing<_T>::printK(){
cout << _k << endl;
}
template<typename _T>
void Thing<_T>::printP(){
cout << _p << endl; // as we can see that i am not using template paramerter "_T"
} // here in this function then why it is required to include template syntax
int main()
{
Thing<int> a(1,2);
a.printK();
a.printP();
}
Because the function PrintK is member of template class Thing<_T>. For a member function definition outside the class, the function name also includes class name(to which it belongs, here it belongs to Thing), since Thing is template, so function name requires you to provide template parameter (T here).
e.g.
Function definition outside class requires the following syntax
**
return type class name:: function name (argument list)
*
Here class (Thing) is template class, so its name will also require type (like Thing<_T>).
I hope you got my point.
Its usually a good idea to restrict the members and functions of a template class to those that are dependent on the template parameters. Non-dependent members and functions can be put in a separate non=template class (is there a better name?). For example:
#include <iostream>
using namespace std;
class ThingBase
{
public:
ThingBase(int p)
: _p(p)
{
}
void printP();
protected:
int _p;
};
void ThingBase::printP(){
cout << _p << endl;
}
template<typename _T>
class Thing : public ThingBase {
_T _k;
public:
Thing(int p, _T k)
: ThingBase(p),
_k(k){}
void printK();
};
template<typename _T>
void Thing<_T>::printK(){
cout << _k << endl;
}
int main()
{
Thing<int> a(1,2);
a.printK();
a.printP();
}

Some basic template problems in C++

I meet with 3 questions when coding C++ with templates. It seems that VS2013 can compile the code below.
Code here:
//template_test.h
#include <iostream>
using namespace std;
template<class T>
class mytest
{
public:
void method(T input);
void common();
};
template <>
class mytest<char>
{
public:
void method(char input);
void common();
};
template<class T>
void mytest<T>::method(T input)
{
cout << input << endl;
}
template<class T>
void mytest<T>::common()
{
cout << "common" << endl;
}
//template_test.cpp
#include "template_test.h"
void mytest<char>::method(char input)
{
cout << "char:" << input << endl;
}
void mytest<char>::common()
{
cout << "common" << endl;
}
//main.cpp
#include "template_test.h"
using namespace std;
int main()
{
mytest<char> test_char;
test_char.method('1');
test_char.common();
mytest<int> test_int;
test_int.method(1);
test_int.common();
system("pause");
return 0;
}
1.In the implementation of mytest::method
template<class T>
void mytest<T>::method(T input)
{
cout << input << endl;
}
Can I erase the second T for short expression? I try the following code instead of original cpp in VS2013,and fail to compile.
template<class T>
void mytest::method(T input)
{
cout << input << endl;
}
It seems so strange that I need to use it in such a complicated form with so many template parameters.
2.In .h file,I delclare the Class 'mytest' using Template Specialization with
template <>
class mytest<char>
{
public:
void method(char input);
void common();
};
and the implementation of each function is in
//template_test.cpp
#include "template_test.h"
void mytest<char>::method(char input)
{
cout << "char:" << input << endl;
}
void mytest<char>::common()
{
cout << "common" << endl;
}
My question is , when I put the implementation in .h file other than in .cpp file together with the implementation of non-specialization template class, VS2013 will also report the error code.
I know the the declaration and implementation of non-specialization template class should be in the same header, for the reason c++ should not permit the expicit of non-specialization template class in other file. But why the declaration and implementation of specialization template class should be in the different code files ?
3.In the header file
template<class T>
class mytest
{
public:
void method(T input);
void common();
};
template <>
class mytest<char>
{
public:
void method(char input);
void common();
};
It is obvious that the function 'common' are the common part of the specialization and non-specialization template class. However, the specialization will specialize the whole class. I just want to reserve the common function ,so there is no need to write the same function in the specialization version. I have no idea how to get it.
I am a newbie in the field of programming with c++ template, and the 3 questions above are basic and easy. I search some questions in Google but still have no idea. So I post my questions here.
Can <T> be omitted from template <typename T> void mytest<T>::method(T input)?
No. Although it seems redundant in simple cases, it becomes necessary in more complex case, e.g., when there are multiple partial specializations are around. Keeping the syntax consistent is also helpful.
When putting the definition of a member function of a fully specialized class template into the header, there is "the" error (I assume you get multiply declared symbols).
The member functions of a fully specialized class template are treated like member functions of a non-class template: there is only one version and the compiler will never need to implicitly instantiate it. Thus, the function is not implicitly inline like it is the case for anything which is a function template and may need to be instantiated by the compiler. If you want to put the definition into the header, you'll need to explicitly declared it as inline.
How can I share a function between a class template and its specialization?
Except for the syntax a class template and any of its specializations have nothing in common. They are entirely separate class. There are two approach to share common functionality between different specializations:
Put the common functionality into a common base class and implement the logic there. If the functionality needs to access members of the actual template, you can use the curiously recurring template pattern to give the base class access to the specialization.
Don't make the common functionality a member function but make it a function template accepting any of the specializations.
Depending on what your common functionality needs to do one or the other approach works better.
A small addition to Dietmar Kühl's answer to 1. Feel the difference:
Implementation of the method of the non-specialized class template template <class T> class mytest:
template <class T>
void mytest<T>::method(T input)
{
// ...
// use of input
}
Implementation of the method of the partial class template specialization template <class T> class mytest<T*> for pointers to objects:
template <class T>
void mytest<T*>::method(T* input)
{
// ...
// use of *input
}
Implementation of the method of the partial class template specialization template <class U, class V> class mytest<U V::*> for pointers to another class data members:
template <class U, class V>
void mytest<U V::*>::method(V& object, U V::* input)
{
// ...
// use of object.*input
}
Implementation of the method of the full class template specialization template <> class mytest<char>:
void mytest<char>::method(char input)
{
// ...
// use of input
}
Implementation of the fully specialized method of the non-specialized class template template <class T> class mytest<T>:
template <>
void mytest<int>::method(int input)
{
// ...
// use of input
}

How to disambiguate function templates that differ only by return type?

I have noticed that there is an asymmetry between the signature used to distinguish unique template functions, and the signature used to distinguish unique functions (including those instantiated from template functions).
In particular, template functions that differ only by return type are considered to be unique, whereas functions that differ only by return type are considered to be redundant.
Therefore, I have a corresponding question about how to disambiguate between function templates that differ only by return type, at the point of instantiation:
#include <iostream>
template<typename T>
long foo(T)
{
std::cout << "long" << std::endl;
return 0;
}
template<typename T>
char foo(T)
{
std::cout << "char" << std::endl;
return '\0';
}
int main()
{
double d = 0.0;
long n = foo(d); // <- Ambiguous: How to specify the template function to use?
}
In the above code, the instantiation of the template function foo is ambiguous precisely because of the asymmetry I've just mentioned. The presence of the two template function definitions is legal, but the instantiation is illegal, even though the return type is specified in the same line of code.
I am asking this question purely for theoretical learning purposes. Perhaps this code construct, in real life, would be a sign of poor design. Perhaps it would never arise in real life. Also, I can envision different ways of overcoming this issue by changing the template definitions (or by making other changes).
However, I would nonetheless like to know if, keeping the template definitions unchanged, it is possible to disambiguate between these two template functions at the point of instantiation.
When using templates you can actually disambiguate the two different overloads. It ain't pretty but works:
long n = static_cast<long(*)(double)>(&foo)(d);
If you really need to have two function templates having the same names, same list of parameters, but different return types, you have no choice but differentiate the two by making the return type a template parameter:
template <typename R, typename T>
R foo(T);
IIRC there is partial function template specialization in C++11, although I could not find anything about it in the standard. If there is, this should work:
//partial function template specializations: C++11 only!
template <typename T>
long foo<long, T>(T)
{
std::cout << "long" << std::endl;
return 0;
}
template<typename T>
char foo<char, T>(T)
{
std::cout << "char" << std::endl;
return '\0';
}
Or else, in C++03:
template <typename R, typename T>
struct FooImpl;
template <typename T>
struct FooImpl<long, T>
{
static long doIt(T)
{
std::cout << "long" << std::endl;
return 0;
}
};
template <typename T>
struct FooImpl<char, T>
{
static char doIt(T)
{
std::cout << "char" << std::endl;
return '\0';
}
};
template <typename R, typename T>
R foo(T t)
{
return FooImpl<R, T>::doIt(t);
}
In both cases, your main would look like this:
int main()
{
double d = 0.0;
long n = foo<long>(d); // specify the return type only
auto c = foo<char>(n);
}