Some basic template problems in C++ - 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
}

Related

Specialisation of member function templates in c++

I want to create a generic class containing a method displaying one message if the type of the class is int and the other when it's double. Here's my code:
template<class T>
class A {
public:
template <T> void B();
};
template<class T>
void A<int>::B{
//some code here
}
template<class T>
void A<double>::B{
//some code here
}
I got the following errors:
'double': illegal type for non-type template parameter '__formal'
'A<int>::B': unable to match function definition to an existing declaration
Thanks in advance for any solutions.
A couple of things:
There's no reason for B to be a template. You want to specialize for A
B is a method. Methods accept parameters. When defining the method, you omitted the parenthesis ()
Template specialization always involves an empty template parameter <>
Code:
template<class T>
class A {
public:
void B();
};
template<>
void A<int>::B(){
std::cout << "A<int>::B" << std::endl;
}
template<>
void A<double>::B(){
std::cout << "A<double>::B" << std::endl;
}
Demo
If you feel compelled to make B a template, I should note that in general one does not perform template specialization on functions. This is primarily because they cannot be partially specialized, and it's almost always better to write an overload. In your case, B takes no arguments, so there's some argument to be made in favor of specialization.
More often than not, one would use a tag dispatching approach instead, coupled with a helper function so that they can choose their desired function by taking advantage of overloading instead. Here's a simple example of tag dispatching for your case:
template<class T>
class A {
public:
template<class U>
void B()
{
B(ATag<U>{});
}
private:
template<class U>
struct ATag{};
void B(ATag<int>)
{
std::cout << "B<int>" << std::endl;
}
void B(ATag<double>)
{
std::cout << "B<double>" << std::endl;
}
};
tag dispatch demo

Partial Template specialization definition outside of class definition

I am having a little trouble with a template specialization. I have looked for other answers, and thought I found the solution in this thread - Partial template specialization outside class definition - however it turns out that does not solve my problem.
I am trying to do some template specialization based on enum values to remove the need for unnecessary run-time polymorphism. When I define the template functions within the class body, it works OK, but when I move the definitions outside of the class template the compiler cannot match the signature.
My actual scenario is interfacing with an API that uses named objects for which each class of objects I am representing with an enum value. The objects are not directly related to each other, but they have very similar resource management / manipulation mechanisms. I initially tried using traits, but because I sometimes need to use completely different function signatures, traits didn't work out as I hoped.
Anyway, here is a cut down example of the problem I am facing.
Dog bark works, because it is defined in the class definition, but Cat meow does not, because it cannot find a declaration of meow. If I merge the definition and declaration cat meow will work.
Is there any way to partially specify templates in this manner? The reason being is that I'd like the dependency on external API's kept to a source file rather than in the header file.
enum class AnimalType { Dog, Cat, };
template<AnimalType Type> struct A;
template<>
struct A<AnimalType::Dog>
{
// OK
void bark() { std::cout << "woof"; }
};
template<>
struct A<AnimalType::Cat>
{
void meow();
};
// Cannot match
template <>
void A<AnimalType::Cat>::meow()
{
}
GCC 4.9 complains
scratchpad/animal.h:105: error: template-id 'meow<>' for 'void <(AnimalType)1>::meow()' does not match any template declaration
void A<AnimalType::Cat>::meow()
Thanks
This:
template<>
struct A<AnimalType::Cat> {
void meow();
};
declares a template specialization with a non-template method. But this:
template <> void A<AnimalType::Cat>::meow()
implies specialization of a template method. Since A<AnimalType::Cat> is already fully-specialized, it doesn't need the template <> here.
Use this instead:
void A<AnimalType::Cat>::meow() {
std::cout << "meow\n";
}
and consider for comparison this template method:
template<>
struct A<AnimalType::Cat> {
template <AnimalType> void greet();
};
template <>
void A<AnimalType::Cat>::greet<AnimalType::Cat>() {
std::cout << "purr\n";
}
template <>
void A<AnimalType::Cat>::greet<AnimalType::Dog>() {
std::cout << "flee\n";
}
Like this works:
// template <>
void A<AnimalType::Cat>::meow()
{
}
As you are defining a member function of the concrete class A<AnimalType::Cat>.

How to specify a member function (inside class is better) by the argument of class template?

I have some class like
enum Type {ONE, TWO};
template <enum Type T>
class A {
void foo() {}
};
I want to specify the function foo() according to the template argument T of the class. Is it possible to be done inside the class ? Or, how to do it outside the class?
Edit:
what if my class is
template <class U, enum Type T>
class A {
void foo() {}
};
This class cannot be simply specialized by giving two version of foo
I found a solution at What is wrong with partial template specialization?
which may turn out to make the code very long.
Is there any other solution to this, or should some other design be used ?
You can explicitly specialize members functions of class templates. You simply do:
template <>
void A<ONE>::foo()
{
//ONE stuff
}
Alternatively, you can use tag-dispatching. In this particular instance, they don't make much sense, but they might if your requirements are slightly different.
template <enum Type T>
class A
{
public:
void foo() {fooImpl(std::conditional_t<T==ONE, std::true_type, std::false_type>());}
void fooImpl(std::true_type)
{
cout << "ONE" << endl;
}
void fooImpl(std::false_type)
{
cout << "TWO" << endl;
}
};
With the above definition,
int main()
{
A<ONE>().foo();
A<TWO>().foo();
return 0;
}
prints
ONE
TWO

What is the difference between 2 forms of specialization template implementation in c++

There are 2 different specialization template forms in c++
One is:
#include <iostream>
using namespace std;
template<class T>
class mytest
{
public:
void method(T input){}
};
template<>
void mytest<int>::method(int input)
{
cout << "ok" << endl;
}
int main()
{
mytest<bool> mt;
mt.method(1);
system("pause");
return 0;
}
The other is:
#include <iostream>
using namespace std;
template<class T>
class mytest
{
public:
void method(T input){}
};
void mytest<int>::method(int input)
{
cout << "ok" << endl;
}
int main()
{
mytest<bool> mt;
mt.method(1);
system("pause");
return 0;
}
They can also be compiled in VS2013. I notice that the second implementation of specialization template situation is just lack of template<>
I want to know what the difference is between the 2 forms above.
Visual C++ is wrong.
The standard is very clear about this.
First,
Members of an explicitly specialized class template are defined in the
same manner as members of normal classes, and not using the template<>
syntax.
Meaning that, for explicit specialization of a class template, the member definition strictly do not require template<>.
Example:
template<class T>
struct A {
};
template<>
struct A<int> {
void f(int);
};
// template<> not used for a member of an
// explicitly specialized class template
void A<int>::f(int) { / ... / }
And,
A member or a member template of a class template may be explicitly
specialized for a given implicit instantiation of the class template,
even if the member or member template is defined in the class template
definition. An explicit specialization of a member or member template
is specified using the syntax for explicit specialization.
Meaning that, for a template that is not "explicit specialized", you can specialize its member, with the template<> (syntax for explicit specialization)
Example,
template<class T>
struct A {
void f(T);
};
// specialization
template<>
void A<int>::f(int);
The above examples are directly copied out from standard. To summarize, if the class is already explicitly specialized, do not use template<>, else if the class relies on implicit instantiation, use template<>.
Your first example compiles fine in Clang, and your second example fails to compile in Clang, you will get an error:
error: template specialization requires 'template<>'
template <class T> class mycontainer { ... };
template <> class mycontainer <char> { ... };
The first line is the generic template, and the second one is the specialization.
When we declare specializations for a template class, we must also define all its members, even those identical to the generic template class, because there is no "inheritance" of members from the generic template to the specialization.
http://www.cplusplus.com/doc/tutorial/templates/

Specialized function in non specialised Template class

Please refer to the below code
Specialized function in non specialized Template class
Is it possible to write a specialized function foo, for non specialized template class MyClass [Line Number 7] ? If yes, then, what is the syntax for the same.
Regards,
Atul
This can be done if you create a full specialization of the class template. Just refer to the answer in this question: If I want to specialise just one method in a template, how do I do it?
Otherwise if you want to have a given function with the same signature have two different behaviors depending on the instantiated version of the class, and that instantiation is a partial specialization of the template class, you will have to make a separate specialization of the template class.
Keep in mind that if you want to avoid redundant code in this second case, you can always create a base template class that will have the functionality that will not change, and then create derived template classes that will contain the unique functionality necessary for each partial specialization.
Look at my example below, I have tried answer your question (if I guessed right) in the simplest code possible by me:
#include <iostream>
using namespace std;
template<typename T>
class Some
{
public:
template<typename U> void foo(U val);
};
template<typename T>
template<typename U>
void Some<T>::foo(U val)
{
cout << "Non specialized" << endl;
}
template<>
template<>
void Some<char>::foo(char val)
{
cout << "Char specialized" << endl;
}
int main()
{
Some<int> t1;
t1.foo(5);
Some<char> t2;
t2.foo('c');
return 0;
}
The important thing to note here is that "You cannot specialize your class and function Independently" i.e you have to specialize both at the same time as done in the example.
Also, with this you lose the opportunity to specialize your class for that data type "char" in this case. (Need to confirm on this).
UPDATE :: Confirmed on point 2.
If you wanted to specialize MyClass< bool >::Foo, it would look like this:
template <>
void MyClass<bool>::Foo(bool A)
{
// code goes here
}
If you are asking that,
(1) you want a function Foo() which doesn't take any argument and
returns void inside MyClass
(2) This Foo() should be exclusive to the MyClass when the
template type is bool, i.e. only for MyClass<bool>
then here is the way:
template<class Precision>
class MyClass {
...
public:
...
void Foo (); // don't implement here
};
...
template<>
void MyClass<bool>::Foo () // implementing only for 'MyClass<bool>'
{ // invoking for other 'MyClass<>' will result in compiler error
...
}