Template Specialization for a function without Parameters - c++

I need to specialize a function template in c++.
template<typename T>
void doStuff<T>() {}
To
template<>
void doStuff<DefinedClass>();
and
template<>
void doStuff<DefinedClass2>();
I guess that is not the correct syntax (since it is not compiling). How should I do it?
Also, Since I will have not undefined template parameters in doStuff<DefinedClass>, would it be possible to declare the body in a .cpp?
Note: doStuff will use T wihtin its body to declare a variable.

The primary template doesn't get a second pair of template arguments. Just this:
template <typename T> void doStuff() {}
// ^^^^^^^^^
Only the specializations have both a template <> at the front and a <...> after the name, e.g.:
template <> void doStuff<int>() { }

The correct syntax for the primary template is:
template <typename T>
void doStuff() {}
To define a specialisation, do this:
template <>
void doStuff<DefinedClass>() { /* function body here */ }

I guess that is not the correct syntax (since it is not compiling). How should I do it?
doStuff will use T wihtin its body to declare a variable.
template<typename T>
void doStuff()
{
T t = T(); // declare a T type variable
}
would it be possible to declare the body in a .cpp?
C++ only supports inclusive mode only, you can't compile separately then link later.
From comment, if you want to specialize for int type:
template<>
void doStuff<int>()
{
}

Related

explicit specialization of a function template (which is a member of a class template) produces "partial specialization is not allowed" error, why?

I am working on Visual Studio 2015 community edition
let's say I have, a simple class like this:
(The example below "should be" a compilable because it include all the necessary stuff, unfortunately, it produces an error).
#include <stdexcept>
template <typename T>
class class_foo
{
// members, methods, constructors. not important stuff...
// helper functions:
private:
class tag_aaa {}; // to resolve few things at compile-time, not run-time.
class tag_bbb {}; // - || -
template <typename tag>
void erase();
// for some reason this is not interpreted as an error by my compiler:
template<>
void erase<tag_aaa>();
template<>
void erase<tag_bbb>();
};
// catch-all-do-nothing "version"
// well, catch-all-throw-an-exception because call to this function is an obvious error.
// that should never occur.
template <typename T>
template <typename tag> inline
void class_foo<T>::erase()
{
throw std::runtime_error("Very weird error...");
}
template <>
template <typename T> inline
void class_foo<T>::erase<class_foo<T>::tag_aaa>()
{
// do some stuff...
}
template <>
template <typename T> inline
void class_foo<T>::erase<class_foo<T>::tag_bbb>()
{
// do some stuff...
}
int main()
{
class_foo<double> bar;
return 0;
}
The error:
1>D:/develop/workspace/visual_studio/nevada_test_site/source/workspace/nevada_test_site/start.cu(36): error : partial specialization of class "class_foo<T>::erase<class_foo<T>::tag_aaa> [with T=T]" is not allowed
1>D:/develop/workspace/visual_studio/nevada_test_site/source/workspace/nevada_test_site/start.cu(43): error : partial specialization of class "class_foo<T>::erase<class_foo<T>::tag_bbb> [with T=T]" is not allowed
1>D:/develop/workspace/visual_studio/nevada_test_site/source/workspace/nevada_test_site/start.cu(51): warning : variable "bar" was declared but never referenced
I think about myself as a junior-hobbyist programmer, so certainly I am wrong, but I believe that both erase<class_foo<T>::tag_aaa>() and erase<class_foo<T>::tag_bbb>() are explicit specializations of the template <typename tag> void erase(); function. And as such, they are allowed. I believe that this error is due to some bad syntax but I can't find an error.
Question:
Is what I am trying to do, allowed?
If yes, what am I doing wrong?
If yes, what is the correct syntax for specializing this functions (erase)?
It look like full specialization of a template function but it's still partial specialization, hence the compilation error.
Why is it? Well, look at this specialization:
template <>
template <typename T>
inline void class_foo<T>::erase<class_foo<T>::tag_bbb>() {
// do some stuff...
}
You said it's a explicit specialization, but there is still a template parameter to fill! There's the parameter T yet to be known. So a specialization... that is still a template? That's a partial specialization!
Partial specialization of function is not allowed, for many reason. One of them is that it won't play nicely with overloading.
To effectively specialize the function, you must leave no template parameter to be known, something like this:
template<>
template<>
inline void class_foo<int>::erase<class_foo<int>::tag_bbb>() {
// do some stuff...
}
But it's not what you want.
Here's how I'd fix this problem. Use overloading instead of specializing:
template<typename T>
struct class_foo {
private:
struct tag_aaa {};
struct tag_bbb {};
void erase(tag_aaa) {
// Stuff when tag_aaa
}
void erase(tag_bbb) {
// Stuff when tag_bbb
}
};
Instead of invoking those like this:
erase<tag_aaa>(); // with specialization
You must invoke it like that:
erase(tag_aaa{}); // with overloading

template function with no object arguments specialization

I'd like to specialize a template function to take non-pointer types and if in case it gets a pointer I'd like to call it without the *.
I'm wondering if there's a way without using std::remove_pointer.
for example I'd like to do something like this:
template<typename T>
void setName() {
name = __PRETTY_FUNCTION__;
}
template<typename T>
void setName<T*>() {
setName<T>();
}
name is defined as a private data member.
Your idea is correct but partial function template specialization is not allowed in C++. Fortuately partial class template specialization is allowed so you can use static method workaround (see specialization of setName_impl below) and if needed function template wrapper (see setName() below):
template<typename T>
struct setName_impl{
static void exec() { }
};
template<typename T>
struct setName_impl<T*>{
static void exec() {
setName<T>::exec();
}
};
template<typename T>
void setName() {
setName_impl<T>::exec();
}

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. */
}

block non-specialized template c++

Is it possible to somehow forbid using templated function for types for which specialization was not explicitly written. I mean something like that
template <typename T>
void foo(){}
template <>
void foo<int>(){}
int main(int argc, char* argv[]){
foo<int>(); //ok
foo<char>(); //Wrong - no specialized version for char.
}
I cannot skip generic version of function, cause then compiler says, that foo is not a template function when i try to specialize. I could simply write something that does not compile in generic function, and add some comment explaining why, but this would be quite non-informative. What i would like to do, is to be able to directly cause compiler to go with error like "foo() is not defined".
Sure: just don't define it and you'll get a linker error if you try to use it:
template <typename T>
void foo(); // not defined
template <>
void foo<int>() { }
Alternatively, you can use some variation of a static assert to give a "nicer" compile-time error. Here is an example using the C++0x static_assert. Note that you must make the false value dependent upon the template parameter, otherwise the static_assert may be triggered when the template is parsed.
template <typename T>
struct dependent_false { enum { value = false }; };
template <typename T>
void foo()
{
static_assert(dependent_false<T>::value, "Oops, you used the primary template");
}
Note that it's usually best not to specialize function templates. Instead, it is better to delegate to a specialized class template:
template <typename T>
struct foo_impl
{
static_assert(dependent_false<T>::value, "Oops, you used the primary template");
};
template<>
struct foo_impl<int>
{
static void foo() { }
};
template <typename T>
void foo()
{
return foo_impl<T>::foo();
}
Sure, just don't supply definition for the default generic template.

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