How do I fully specialize a function template with a class template? - c++

template <typename T>
void foo(T t)
{
... // do stuff with type T
}
template <typename T>
class class_template
{
// class body
};
template<> // failed attempt at full specialization
void foo(class_template<T> t) // which doesn't work of course
{
//full specialization for all classes of class_template
}
In the above code how do I explicitly specialize function foo with a class template?

In the above code how do I explicitly specialize function foo with a class template?
You cannot. This is the whole point of partial specialisations. But they don’t work for functions.
You have two solutions:
Overload the function. This usually works.
Refer the work to a class template, which can be partially specialised. That is, inside your function, call a (static) function in a class template, and specialise that.

Related

Member function of class with template arguments and default arguments outside class

I want to define function outside the template class as described below.
Already tried a lot of combinations for the second argument which is a template and takes default argument as well.
template <typename T>
class CustomAllocator
{
//My custom allocator
};
template <typename T, typename Allocator = CustomAllocator<T> >
class CustomContainer
{
void push_back();
};
/*I want to define push_back outside my class, tried everything.
Almost 4 hours spent through stackoverflow, fluentcpp and all sites*/
// What should be specified for Allocator here ?
template <typename T>
void CustomContainer<T,Allocator>::push_back(T value)
{
}
//OR
template <typename T>
void CustomContainer<T,CustomAllocator<> >::push_back(T value)
{
}
I expect it to be defined outside class
Actual getting compiler error, if it is simple type I could easily mention int,float etc. in the second argument.
Outside of your class definition, it will be unclear to a function what type Allocator is, so you have to redeclare it just like you redeclared T
template <class T, class Allocator>
void CustomContainer<T,Allocator>::push_back(T value)
{
// ...
}
(I'm assuming that DataType should be T)
Note that your declaration of push_back, in the class should match the definition:
template <typename T, typename Allocator = CustomAllocator<T> >
class CustomContainer
{
void push_back(T);
};
You may not use default template arguments for a member function of a template defined outside the template definition.
From the C++ 17 Standard (17.1 Template parameters)
... A default template-argument shall not be specified in the template-
parameter-lists of the definition of a member of a class
template that appears outside of the member’s class.
So just write
template <typename T, typename Allocator>
void CustomContainer<T, Allocator>::push_back( const T &value )
{
//...
}
Pay attention to the argument of the function. Your declaration of the function does not correspond to its definition.

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
{
...
};

how to specialize template member functions in template class?

For example:
template<unsigned number>
struct A
{
template<class T>
static void Fun()
{}
};
And want to specialize A<1>::Fun()
template<>
A<1>::Fun<int>()
{
/* some code here. */
}
doesn't work. How to do it? Thanks.
First of all, you forgot to specify the return type of the function (void). Secondly, you need to have two template<>: one because you are explicitly specializing the class template, and one because you are explicitly specializing its member function template.
Therefore, this is the correct syntax:
template<> // Because you are explicitly specializing the A class template
template<> // Because you are explicitly specializing the `Fun()` member template
void A<1>::Fun<int>()
{
/* some code here. */
}

Template specialization with struct and bool

I have a template class in which I am specializing a couple of methods. For some reason, when I added a specialization for a struct, it seems to be conflicting with the specialization for bool. I am getting a type conversion error because it is trying to set the struct = bool (resolving to the wrong specialization). Here is some code
.h:
typedef struct foo {
...
}
template <class T> class bar {
template <class T> void method1() {...}
template <> void method1<bool>() {...}
template <> void method1<foo>() {...}
}
.cpp
template class bar<bool>;
template class bar<foo>;
I am getting the error inside method1<bool> because it is setting T=foo instead of resolving it to method1<foo>.
Any ideas?
The first part of your code is already incorrect. C++ does not support explicit specialization of "nested" (member) templates without explicit specialization of the enclosing template.
In the context of your code, it is illegal to explicitly specialize template method method1 without explicitly specializing the entire class template bar.
If your member template function member1 depended on some parameters, you could use overloading instead of template specialization as a workaround. But since it doesn't, you have to redesign you templates somehow. What you do above is, once again, illegal in C++.
The errors you get further down can easily be (and most probably are) induced by that original problem.
P.S. The description of the problem you posted implies that your code compiles. What you posted should not compile for the reasons described above. This suggests that you are posting fake code. Post real code.
(EDITED)
You may try the following, which delegates the method implementation to a templated helper class.
.h:
typedef struct Foo {
...
}
template<class T_Bar, class T2> struct BarMethod1;
template <class T> class Bar
{
template<class T2> void method1(...)
{
BarMethod1<Bar, T2>(...)(...);
}
}
template <class T_Bar, class T2> class BarMethod1
{void operator()(...){...}};
template <class T_Bar> class BarMethod1<T_Bar, bool>
{void operator()(...){...}};
template <class T_Bar> BarMethod1<T_Bar, Foo>
{void operator()(...){...}};
.cpp
template class Bar<bool>;
template class BarMethod1<Bar<bool>, bool>;
template class BarMethod1<Bar<bool>, Foo>;
template class Bar<Foo>;
template class BarMethod1<Bar<Foo>, bool>;
template class BarMethod1<Bar<Foo>, Foo>;

Difference between member functions for a template class defined inside and outside of the class

Is there a difference between defining member functions for a template class inside the class declaration versus outside?
Defined inside:
template <typename T>
class A
{
public:
void method()
{
//...
}
};
Defined outside:
template <typename T>
class B
{
public:
void method();
};
template <typename T>
void B<T>::method()
{
//...
}
For non-template classes, this is the difference between inlined and non-inlined methods. Is this also true for template classes?
The default for most of my colleagues is to provide definitions inside the class, but I've always preferred definitions outside the class. Is my preference justified?
Edit: Please assume all the above code is provided in the header file for the class.
Yes, the exact same is true for template classes.
The reason why method definitions for template classes are usually preferred to be inline is that with templates, the entire definition must be visible when the template is instantiated.
So if you put the function definition in some separate .cpp file, you'll get a linker error.
The only general solution is to make the function inline, either by defining it inside the class or outside with the inline keyword. but in either cases, it must be visible anywhere the function is called, which means it must typically be in the same header as the class definition.
There's no difference, aside from having to type more. That includes the template bit, the inline and having to use more "elaborate" names when referring to the class. For example
template <typename T> class A {
A method(A a) {
// whatever
}
};
template <typename T> inline A<T> A<T>::method(A a) {
// whatever
}
Note that when the method is defined inside you can always omit the template parameter list <T> when referring to A<T> and just use A. When defining it outside, you have to use the "full" name in the return type and in the name of the method (but not in the parameter list).
I know this..I think it must be some what help full to u?
defining a member function outside of its template
It is not ok to provide the definition of a member function of a template class like this:
// This might be in a header file:
template <typename T>
class xyz {
void foo();
};
// ...
// This might be later on in the header file:
void xyz<T>::foo() {
// generic definition of foo()
}
This is wrong for a few reasons. So is this:
void xyz<class T>::foo() {
// generic definition of foo()
}
The proper definition needs the template keyword and the same template arguments that the class template's definition was declared with. So that gives:
template <typename T>
void xyz<T>::foo() {
// generic definition of foo()
}
Note that there are other types of template directives, such as member templates, etc., and each takes on their own form. What's important is to know which you have so you know how to write each flavor. This is so especially since the error messages of some compilers may not be clear as to what is wrong. And of course, get a good and up to date book.
If you have a nested member template within a template:
template <typename T>
struct xyz {
// ...
template <typename U>
struct abc;
// ...
};
How do you define abc outside of xyz? This does not work:
template <typename U>
struct xyz::abc<U> { // Nope
// ...
};
nor does this:
template <typename T, typename U>
struct xyz<T>::abc<U> { // Nope
// ...
};
You would have to do this:
template <typename T>
template <typename U>
struct xyz<T>::abc {
// ...
};
Note that it's ...abc not ...abc<U> because abc is a "primary" template. IOWs, this is not good:
// not allowed here:
template template struct xyz::abc { };