c++ template specialisation method definition - c++

The following code works fine, a simple template class with a definition and a use
#include <string>
#include <iostream>
using namespace std;
template<class T> class foo{
public:
string what();
};
template<class T> string foo<T>::what(){
return "foo of type T";
}
int main(){
foo<int> f;
cout << f.what() << endl;
}
If I then add the following (above main, but after the declaration of template class foo;)
template<> class foo<char>{
public:
string what();
};
template<> string foo<char>::what(){
return "foo of type char";
}
I get an error from g++
Line 19: error: template-id 'what<>'
for 'std::string foo::what()'
does not match any template
declaration
Here is a codepad the shows the error: http://codepad.org/4HVBn9oJ
What obvious misstake am I making? Or is this not possible with c++ templates?
Will defining all the methods inline (with the defintion of template<> foo) work?
Thanks again all.

template<> class foo<char>{
public:
string what();
};
/*template<>*/ string foo<char>::what(){
return "foo of type char";
}
You don't need that template<>. foo<char> is already a complete type after it's specialized.

Writing this as:
#include <string>
#include <iostream>
using namespace std;
template<class T> class foo{
public:
string what();
};
template<class T> string foo<T>::what(){
return "foo of type T";
}
template<> class foo<char>{
public:
string what();
};
string foo<char>::what(){
return "foo of type char";
}
int main(){
foo<char> f;
cout << f.what() << endl;
}
works as expected.

If I then add the following (above main, but before the declaration of template class foo;)
Define the specialization after the generic class template.
By the time the compiler sees the specialization, it first needs to know the class template of which this is a specialization. So logically, the specialization should appear after the generic class template.

Related

Inner template classes inheritance

I have the following code: https://gist.github.com/PatrikValkovic/50329975f86e0328ff1f85fda17a23f3, live example here: http://cpp.sh/675a3.
In short, I have class A with inner class B<U> and class D that should inherit from the B<U>. The code works when the class D is declared within class A (as commented). However, when I move the declaration outside of the class A (as in the example), the compiler complains, that A<T>::B<U> is not a type. What is wrong about the syntax?
// Example program
#include <iostream>
#include <string>
using namespace std;
template<typename T>
class A
{
public:
template<typename U>
class B;
/*
class D : public B<int>
{
public:
void method2() {
cout << "Method 2" << endl;
this->method1();
}
};
*/
class D;
};
template<typename T>
template<typename U>
class A<T>::B
{
public:
void method1() {
T x;
cout << "Method 1: " << x << endl;
}
};
template<typename T>
class A<T>::D : public A<T>::B<int>
{
public:
void method2() {
cout << "Method 2" << endl;
this->method1();
}
};
int main()
{
A<int>::D b;
b.method2();
}
This is one of those really weird edge cases in the C++ language that has a unusual fix. The issue is here:
template<typename T>
class A<T>::D : public A<T>::B<int>
^^^^^^^^^^^^
The problem is that you are trying to use the template class B, which is a dependent name inside of A (that is, B is a template nested inside another type that depends on a template argument, here, T). By default, C++ won't treat dependent names as being names of types or names of templates, and you have to explicitly tell the compiler "yes, this is the name of a template" by using the template keyword in an unusual way:
template<typename T>
class A<T>::D : public A<T>::template B<int>
^^^^^^^^
This tells C++ "inside of A<T>, you're going to find a template type named B. Please use that template with argument int."
This is similar to how you have to use the typename keyword with dependent types - it tells the compiler "yes, this is the name of a type." Here, the template keyword tells the compiler "yes, this is the name of a template."

undefined reference to full template specialization class member function, but not partial specialization

so i got an undefined reference error when using template explicit instantiation with full template class specialization, but the question is, partial template class specialization goes well without error.
code shows as below, do anyone know why? what's the difference between full specialization and partial specialization in this situation?
Thanks in advance.
// t.h
#include <iostream>
using namespace std;
template <typename T1, typename T2>
class A {
public:
void foo();
};
// t2.cpp
#include "t.h"
template<typename T1>
class A<T1, int> {
public:
void foo() {
cout << "T1, int" << endl;
}
};
template<>
class A<int, int> {
public:
void foo() {
cout << "int, int" << endl;
}
};
template class A<float, int>;
template class A<int, int>;
// t.cpp
#include "t.h"
int main() {
A<float, int> a;
a.foo(); // no error
A<int, int> a1;
a1.foo(); // undefined reference error, why?
return 0;
}
the compile commands are g++ t.cpp t2.cpp -o t with gcc 4.8.5.
You have to declare partial and explicit specializations in every translation unit that uses them (before any use that would implicitly instantiate that specialization). Here, that would look like
template<class T> class A<T,int>;
template<> class A<int,int>;
immediately after the primary template (to avoid any possibility of erroneous implicit instantiation.
Compilers have historically been “lax” about this, which is to say that sometimes it does what you’d expect from an analysis of all source files together.
You’ve found the edge of such accidental “support” in this particular compiler.

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();
}

Specializations only for C++ template function with enum non-type template parameter

This question is related to this one except that rather than dealing with typename template parameters, I am trying to use an enum non-type template parameter.
Is it possible to have a templated (class member function) with only specializations, no general (working) definition in the case of non-type template parameter?
I was able to get one version working, by declaration in the class body and providing specializations only, but any misuse calling with a non-defined template parameter doesn't produce an error until linking. What's worse is the missing symbol cryptically refers to the enum's integral value and not its name, so it would be confusing to other developers.
I was able to get the BOOST_STATIC_ASSERT technique from the referenced question to work for typename template parameter only.
This code demonstrates the idea. I don't want the CAT-version call to compile:
#include <iostream>
#include <boost/static_assert.hpp>
// CLASS HEADER FILE:
struct foo_class
{
enum AllowedTypes { DOG, CAT };
template <AllowedTypes type>
void add_one_third( double bar ) const
{
BOOST_STATIC_ASSERT_MSG(sizeof(type)==0, "enum type not supported.");
}
};
// CLASS SOURCE FILE
template<>
void foo_class::add_one_third<foo_class::DOG>( double bar ) const
{
std::cout << "DOG specialization: " << bar + 1./3. << std::endl;
}
// USER SOURCE FILE
int main()
{
std::cout << "Template Specialization!\n\n";
foo_class a;
a.add_one_third<foo_class::DOG>(3.0); // should succeed
// Compilation fails with or without the following line:
a.add_one_third<foo_class::CAT>(3.0); // should fail at compile-time
return 0;
}
Background:
I have a class member function that takes an enum "ArgType" and a name.
void declareKernelArgument( ArgType type, std::string name );
The definition has turned into an if..else..if..else list for the half-dozen or so allowed ArgType cases. I also have to have final case that throws an exception for an not-allowed ArgType. I'm thinking it would be cleaner to move ArgType to a template parameter, and provide a specialization for each allowed ArgType. Misuse would be caught at compile-time.
With partial specialization of a structure inside the class:
#include <iostream>
class foo_class
{
public:
enum AllowedTypes { T_DOUBLE, T_INT };
private:
template <AllowedTypes type, typename T>
struct AddOneThird;
template <typename T>
struct AddOneThird<T_DOUBLE, T> {
static void apply(T bar) {
std::cout << "T_DOUBLE specialization: " << bar + 1.0/3.0 << std::endl;
}
};
public:
template <AllowedTypes type>
void add_one_third( double bar ) const {
AddOneThird<type, double>::apply(bar);
}
};
int main() {
foo_class a;
a.add_one_third<foo_class::T_DOUBLE>(3.0);
// error: incomplete type ‘foo_class::AddOneThird<(foo_class::AllowedTypes)1u
// a.add_one_third<foo_class::T_INT>(3.0); // should fail at compile-time
return 0;
}
With full specialization of a (friend) class:
#include <iostream>
class foo_class
{
public:
enum AllowedTypes { T_DOUBLE, T_INT };
// if needed
// template<AllowedTypes> friend struct AddOneThird;
public:
template <AllowedTypes type> void add_one_third( double bar ) const;
};
template <foo_class::AllowedTypes>
struct AddOneThird;
template <>
struct AddOneThird<foo_class::T_DOUBLE> {
static void apply(double bar) {
std::cout << "T_DOUBLE specialization: " << bar + 1.0/3.0 << std::endl;
}
};
template <foo_class::AllowedTypes type>
void foo_class::add_one_third( double bar) const {
AddOneThird<type>::apply(bar);
}
int main() {
foo_class a;
a.add_one_third<foo_class::T_DOUBLE>(3.0);
// error: incomplete type ‘AddOneThird<(foo_class::AllowedTypes)1u>’ used
// in nested name specifier
//a.add_one_third<foo_class::T_INT>(3.0); // should fail at compile-time
return 0;
}
Utilizing C++11 or boost::enable_if:
#include <iostream>
#include <type_traits>
class foo_class
{
public:
enum AllowedTypes { T_DOUBLE, T_INT };
template <AllowedTypes type>
typename std::enable_if<type == T_DOUBLE>::type
add_one_third( double bar ) const {
std::cout << "T_DOUBLE specialization: " << bar + 1.0/3.0 << std::endl;
}
};
int main() {
foo_class a;
a.add_one_third<foo_class::T_DOUBLE>(3.0);
// error: no matching function for call to ‘foo_class::add_one_third(double)’
//a.add_one_third<foo_class::T_INT>(3.0); // should fail at compile-time
return 0;
}
From Herb Sutter
It's a lot less intuitive to specialize function templates. For one thing, you can't partially specialize them -- pretty much just because the language says you can't.[2] For another thing, function template specializations don't overload. This means that any specializations you write will not affect which template gets used, which runs counter to what most people would intuitively expect. After all, if you had written a nontemplate function with the identical signature instead of a function template specialization, the nontemplate function would always be selected because it's always considered to be a better match than a template.
If you're writing a function template, prefer to write it as a single function template that should never be specialized or overloaded, and implement the function template entirely in terms of a class template. This is the proverbial level of indirection that steers you well clear of the limitations and dark corners of function templates. This way, programmers using your template will be able to partially specialize and explicitly specialize the class template to their heart's content without affecting the expected operation of the function template. This avoids both the limitation that function templates can't be partially specialized, and the sometimes surprising effect that function template specializations don't overload. Problem solved.
Your enum type sizeof is not 0, change that to 4 at least. Otherwise this will not work. A enum element size is not 0.
Without that everything runs
#include <iostream>
struct foo_class
{
enum AllowedTypes { DOG, CAT };
template <AllowedTypes type>
void add_one_third( double bar ) const
{
std::cout << "YES" << std::endl;
}
};
template<>
void foo_class::add_one_third<foo_class::DOG>( double bar ) const
{
std::cout << "DOG specialization: " << bar + 1./3. << std::endl;
}
int main()
{
std::cout << "Template Specialization!\n\n";
foo_class a;
a.add_one_third<foo_class::DOG>(3.0); // should succeed
// Compilation fails with or without the following line:
//a.add_one_third<foo_class::CAT>(3.0); // should fail at compile-time
return 0;
}
The main difference between the enum case and the referenced question using a typename parameter is that the default definition will be compiled for any use. So, a working solution is as simple as modifying the BOOST_STATIC_ASSERT condition to check allowed enum values.
#include <iostream>
#include <stdexcept>
#include <boost/static_assert.hpp>
// CLASS HEADER FILE:
struct foo_class
{
enum AllowedTypes { DOG, CAT, MOUSE };
template <AllowedTypes type>
void give_bath() const
{
// compile fails if ever attempting to use this function with CAT parameter.
BOOST_STATIC_ASSERT_MSG( (type==DOG) || (type==MOUSE) , "enum type not supported.");
throw std::runtime_error("Unexpected. Above list inconsistent with specializations.");
}
};
// CLASS SOURCE FILE
template<>
void foo_class::give_bath<foo_class::DOG>() const
{
std::cout << "DOG is bathed." << std::endl;
}
template<>
void foo_class::give_bath<foo_class::MOUSE>() const
{
std::cout << "MOUSE is bathed." << std::endl;
}
// USER SOURCE FILE
int main()
{
std::cout << "Template Specialization!\n\n";
foo_class a;
a.give_bath<foo_class::DOG>(); //success
a.give_bath<foo_class::MOUSE>(); // success
// Compilation fails with the following line:
//a.give_bath<foo_class::CAT>(); // fails at compile-time as intended.
return 0;
}
Of course, the whole design smells bad and could likely be handled more elegantly with AllowedTypes being a struct/class with inherited specializations. But this gets to the question at hand.

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/