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
...
}
Related
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
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
I have a templated class which contains a static function which does not depend on the template parameter. Yet the compiler seems to force me to specify a typename when I use the function.
template <typename T>
class MyClass {
...
static void function();
};
template <typename T>
void MyClass<T>::function() {
....
}
This function can be used as:
MyClass<int>::function();
But the 'int' is just there to satisfy the compiler. It doesn't mean anything, and can be replaced by any other type, which doesn't increase code readability. I would like to do someting like
MyClass<>::function();
or even
MyClass::function();
but the compiler doesn't let me. I realize that this is because in the header files I have explicitly marked the function as being templated, but when I remove the '< T >' from the header file it doesn't compile either.
What is the correct way to do this?
The type is very important!
Templates can be specialized, and therefore:
template <typename T>
class MyClass {
public:
static void function() { std::cout << "Hello, World!\n"; }
};
template <>
class MyClass<City> {
public:
static void function() { launchRockets(); }
};
is a viable program.
If you then write MyClass::function(), should it annihilate Bagdad or print a friendly message ?
Of course, if there is no reason for this function to do anything else that printing, then it should perhaps be a function on its own:
void function() { std::cout << "Hello, World!\n"; }
which is invoked simply by function(), hey, it's even shorter as there is no class!
Imagine you had this:
template <typename T> struct Foo
{
static void boom()
{
static int n = 0;
std::cout << ++n << std::endl;
}
};
Now imagine what happens if you say Foo<int>::boom(); Foo<int>::boom();, and compare that to the not-at-all equivalent Foo<int>::boom(); Foo<char>::boom();.
Don't think of a template as a class. It's just a skeleton on which classes are built.
MyClass::function() doesn't have any meaning, since MyClass is not an actual class unless you specialize it.
MyClass<int>::function(); and MyClass<char>::function(); might not depend on the template parameter, they might behave the same, but they are not the same function.
Let's take a look at the binary:
MyClass<int>::function();
00D617CE call MyClass<int>::function (0D611C2h)
MyClass<char>::function();
00D617D3 call MyClass<char>::function (0D611C7h)
For this, I provided an empty definition for function, so it definitely doesn't depend on the template parameter. As you can see, the two functions are different.
That's because there are two classes there generated by the compiler - MyClass<int> and MyClass<char>.
When I want to define a method declared in a template class, but that the method doesn't depend on the template parameters, have I to define it in the include files as :
template class<typename T>
void MyClass::myMethod()
{
...
}
or may I define it in the cpp file as :
void MyClass::myMethod()
{
...
}
?
Thanks.
You'll need to define your method like this:
template class<typename T>
void MyClass<T>::myMethod()
{
// Method Body
}
The reason for this is that the method actually is dependent on the template parameter. Remember that every method has access to the special variable this; during the method call this is actually a parameter passed to the method. this changes in type depending on the template parameter specified during object instantiation and, as such, all methods must be template methods in order to accommodate all forms of this.
Well, if the method doesn't depend on template parameter, you can only do that with inheritance AFAIK.
The downside: more code + inheritance
The upside: (much) less code generated, depending on what parts of your code actually are template dependent. In the below example, method NonDependentMethod will only generate one assembly while DependentMethod will generate as many as there are different template parameters (just one in this case, but make a MyClass<float> and you have two, etc).
#include <iostream>
using namespace std;
class MyClassBase
{
public:
void NonDependentMethod();
};
template <class T> class MyClass : public MyClassBase
{
public:
void DependentMethod(T param);
};
void MyClassBase::NonDependentMethod()
{
cout << "NonDependentMethod" << endl;
}
template<class T> void MyClass<T>::DependentMethod(T param)
{
cout << "DependentMethod " << param << endl;
}
int main() {
// your code goes here
MyClass<int> cls;
cls.NonDependentMethod();
cls.DependentMethod(2);
return 0;
}
Put it in the header file.
The member function is still a member of the class template, and you'd have to write:
template <typename T> void MyClass<T>::myMethod() { /* ... */ }
As with all template member functions, this isn't actually a real function yet; it only generates a real function when the class template is instantiated. So the full template definitions have to be visible to everyone who instantiates the template, and the usual way of doing this is by putting everything in the header.
(Note that member functions of class templates are themselves considered function templates, and you can actually specialize them: template <> void MyClass<int>::myMethod() { }.)
You need to do it this way:
template class<typename T>
void MyClass<T>::myMethod()
{
...
}
It's not the method that is templated, it's the class.
You can have a templated method in a non-templated class, a non-templated method in a templated class (your case) and a templated method in a templated class, and of course a non-templated method in a non-templated class.
You have to define it in an even other way. The method itself may not (directly) depend on the template parameter, but the class to which it belongs certaily does, no? As such, the method indirectly depends on the template parameter too:
template class<typename T>
void MyClass<T>::myMethod()
{ // ^^^ -- note
...
}
I would like to have several different function definitions for a member function in a templated class. Something like this:
template <typename T>
class MyClass
{
void Foo();
T val;
//other functionality and data
};
//handles all types
template <typename T>
void MyClass<T>::Foo()
{
return val;
}
//handles a special type in a different way
template <>
void MyClass<float>::Foo()
{
return val + 5.0f;
}
I've tried implementing this as above and get a linker error for every special type I try to explicitly instantiate. The linker error mentions that the function has already been previously defined. Maybe I'm looking in the wrong places but I couldn't find any resources to help me figure out this problem :(
Q. Is this possible? If so, how do you do this and why does it work?
Thanks!
Here is a workaround that I frequently use. As it as been said before, you have to specialize the complete template. The idea is to make the method you want to specialize a static member of some struct (that should be nested and private for encapsulation reasons). Like this:
template< typename T >
class MyClass {
struct PerformFoo {
static void doFoo () {
std::cout << "Foo for general type" << std::endl;;
}
};
public:
void Foo () {
PerformFoo::doFoo();
}
};
template<>
struct MyClass< float >::PerformFoo {
static void doFoo () {
std::cout << "Foo for float" << std::endl;;
}
};
Now in your main, the code
MyClass< int > myInt;
myInt.Foo();
MyClass< float > myFloat;
myFloat.Foo();
prints
Foo for general type
Foo for float
on your terminal. By the way: this does not involve any performance penalty with modern compilers. Hope this helps you.
By defining the specialized member function as inline function you will get rid of the link error complaining the specialized member function having been defined elsewhere.
//handles a special type in a different way
template <>
inline void
MyClass<float>::Foo()
{
return val + 5.0f;
}
The reason being that a specialized function is no longer a function template, but a concrete function. Therefor it will be compiled several times when compiling source files that includes this header file which is why you get the "already defined" error.
Another solution is to move the implementation of the specialized function out of the header file and put it into the source file, meanwhile, declare the specialized function in the header file. Note that the declaration of the specialized member function must stay outside of the class definition:
/// Declare the specialized function in the header file but outside the
/// class definition.
template <> void MyClass<float>::Foo()
/// Define the specialized function in .cpp file:
template <>
void
MyClass<float>::Foo()
{
return val + 5.0f;
}
I've tried implementing this as above and get a linker error for every special type I try to explicitly instantiate.
What does that mean? If you explicitly specialize the template you cannot explicitly instantiate it anymore for the same template arguments. The whole purpose of an explicit specialization is to prevent the instantiation of it (which is a generated specialization) in favor of your explicit specialization.
So your description does not make sense to me. Just remember that you need to put definitions of templates and member functions of class templates in the header instead of in the .cpp file if you want to instantiate them implicitly. And that explicit specializations need to be declared to everyone who uses their template with their arguments.
// put this specialization into the header, for everyone to see
template <> void MyClass<float>::Foo();
It is not possible. When you specialize a template, you must specialize the entire template, which in this case means the entire class.
You can make foo a template function inside the template class. It is not exactly the same as what you are asking for, but it might meet your needs.
Update:
template<typename T> class Foo {
public:
template<typename R> void foo() {printf("This is foo\n");}
template<> void foo<float>() {printf("This is foo<float>\n");}
};
Or:
template<typename T> class Foo {
public:
template<typename R> void foo() {printf("This is foo\n");}
//template<> void foo<float>() {printf("This is foo<float>\n");}
};
template<> template<> void Foo<float>::foo<float>() {
printf("This is foo<float>\n");
}
along with:
int main(int argc,char * argv[])
{
Foo<int> iFoo;
iFoo.foo<int>();
Foo<float> fFoo;
fFoo.foo<float>();
return 0;
}
generates:
This is foo
This is foo<float>
The syntax for calling foo is a bit awkward.