Template specialization of pure virtual method - c++

Expected this code to compile and work
template<class T>
class Base
{
virtual void method() = 0;
};
template<>
void Base<int>::method() { std::cout << "overrided" << std::endl; }
Base<int> base;
But it gives the 'Base<int>': cannot instantiate abstract class error. Thought partial specialization would make Base<int> non-abstract and allow to instantiate it.
Is there a working solution as short as this one and that keeps the Base class abstract? Otherwise I can make the Base class non-abstract or use Nicol Bolas's solution from here: Template specialization and inheritance

If it won't work for a non-template class, why should it work for a template class?
#include<iostream>
class Base
{
virtual void method() = 0;
};
void Base::method() { std::cout << "overrided" << std::endl; }
Base base;
errors:
10 : error: cannot declare variable 'base' to be of abstract type 'Base'
Base base;
^
3 : note: because the following virtual functions are pure within 'Base':
class Base
^
8 : note: virtual void Base::method()
void Base::method() { std::cout << "overrided" << std::endl; }
^
Compilation failed

What about specialization of whole class (instead of just one member function):
template<class T>
struct TempClass
{
virtual void f() = 0;
};
template <>
struct TempClass<int>
{
virtual void f()
{
//...
}
};
Note that TempClass<int> is no longer abstract class, but other Base classes are still abstract classes, (TempClass<float>, TempClass<double>, TempClass<SomeClassType>, ...).
and
it won't contain fields that generic class TempClass contains. You will have to copy-paste them from generic Base or, which is more clever solution,
you'll create base class with fields that both specialization have and then make those template classes inherit from that base class:
template <typename T>
struct Base
{
// some members that all Base classes have
};
template <typename T>
struct TempClass: Base<T>
{
virtual void f() = 0;
};
template <>
struct TempClass<int>: Base<int>
{
virtual void f()
{
//...
}
};
This way ugly copy-paste wasn't needed.

It is possible to provide an implementation of a pure virtual function in a class. That does not make the class instantiable.
class Base
{
virtual void method() = 0;
};
void Base::method() { /* Do something */ }
// This is still a problem since Base
// is still an abstract class, i.e. it is not still not
// instantiable.
Base base;

Related

Why does an overriden template class method still get compiled?

When I create a templated class with a virtual function, and override the function in a derived class, the base function still tries to get compiled.
Here is the minimal reproducible example:
#include <iostream>
template<typename T>
class Base
{
public:
virtual void Method()
{
static_assert(false);
}
};
class Derived : public Base<int>
{
public:
void Method() override
{
std::cout << "Hello, World!";
}
};
int main()
{
Derived d{};
d.Method();
return 0;
}
Why does the base method still try to compile when it is overriden?
First, it needs to be compiled as user can instantiate Base<T> and directly call Method() on it. If you wanted to make it non-callable, use virtual void Method() = 0; for abstract functions.
Second, not only compiled, it's actually accessible from Derived: you can call it e.g. from Derived::Method(), as Base<int>::Method().

Use specialization from base class

I have a class that inherits from a base class. The derived class has a template method. The base class has a specialized version of this method:
#include <iostream>
class Base {
public:
static void print(int i) { std::cout << "Base::print\n"; }
};
class Derived : public Base {
public:
static void print(bool b) { std::cout << "Derived::bool_print\n"; }
template <typename T>
static void print(T t) { std::cout << "Derived::print\n"; }
void Foo() {
print(1);
print(true);
print("foo");
}
};
int main()
{
Derived d;
d.Foo();
return 0;
}
The output is:
Derived::print
Derived::bool_print
Derived::print
The desired output is:
Base::print
Derived::bool_print
Derived::print
See code at https://onlinegdb.com/BY2znq8WV
Is there any way to tell Derived::Foo to use the specialization from Base instead of using the unspecialized version define in Derived?
Edit
The above example might be oversimplified as #Erdal Küçük showed. In actuality Derived subclasses from Base using CRTP, so it is not known if Base has a print method. A fuller example can be found at https://onlinegdb.com/N2IKgp0FY
This might help:
class Derived : public Base {
public:
using Base::print; //one of the many useful usages of the keyword 'using'
//...
};
See: Using-declaration in class definition

C++: inherited classes have pure virtual functions with identical names. How can I override them separately in my base class?

The following code illustrates my question:
namespace foo1
{
class bar1
{
public:
virtual void fn() = 0; //this must remain pure virtual
};
};
namespace foo2
{
class bar2
{
public:
virtual void fn() = 0; //this must remain pure virtual
};
};
class bar3: public foo1::bar1, public foo2::bar2
{
public:
//can i separately override virtual functions from inherited
//classes that have the same name?
void foo1::bar1::fn() override {std::cout << "bar1";} //error
void foo2::bar2::fn() override {std::cout << "bar2";} //error
};
int main()
{
bar3* obj = new bar3();
((foo1::bar1*)obj)->fn(); //i want this to print "bar1"
((foo2::bar2*)obj)->fn(); //and this to print "bar2"
}
Basically I want to be able to override inherited functions, such that by simply casting my base class object to one of the inherited classes, I can call the different functions even though they have the same name. Is this possible?
Sure.
struct foo1bar1helper:public foo1::bar1{
void fn()final{foo1bar1fn();}
virtual void foo1bar1fn()=0;
};
now bar3 just inherits from this instead of bar1 and overrides foo1bar1fn(),
Do the same with bar2.
You can also use CRTP to dispatch and do away with the extra vtable lookup;
template<class D>
struct foo1bar1helper:public foo1::bar1{
void fn()final{static_cast<D*>(this)->foo1bar1fn();}
};
template<class D>
struct foo2bar2helper:public foo2::bar2{
void fn()final{static_cast<D*>(this)->foo2bar2fn();}
};
class bar3:
public foo1bar1helper<bar3>,
public foo2bar2helper<bar3>
{
public:
void foo1bar1fn(){}
void foo2bar2fn(){}
};
You can not do that. When you do foo1::bar1::fn(), compiler thinks that you are defining function fn of 'bar1' of 'foo1' namespace in class bar3. Hence compiler is throwing below error.
error: cannot define member function ‘foo1::bar1::fn’ within ‘bar3’
But when you extend from an abstract class, you need to give the definition of the function (which should be part of your derived class) in derived class.

Is it safe if a template contains virtual function?

Early binding for template and late binding for virtual function. Therefore, is it safe if a template contains virtual function?
template<typename T>
class base {
public:
T data;
virtual void fn(T t){}
};
It is completely safe. Once you instantiate the class template, it becomes normal class just like other classes.
template<typename T>
class base {
public:
T data;
virtual void fn(T t){}
};
class derived : base<int> {
public:
virtual void fn(int t){} //override
};
base<int> *pBase = new derived();
pBase->fn(10); //calls derived::fn()
I would also like to point out that while it is allowed virtual function in a class template, it is not allowed virtual function template inside a class (as shown below):
class A
{
template<typename T>
virtual void f(); //error: virtual function template is not allowed
};
Yes, it's quite safe. You'd use it by having a class derive from it:
class derived : public base<int> {
virtual void fn(int) { std::cout << "derived"; }
};
Of course, if it contains any other virtual functions (i.e., is intended to be used as a base class) you generally want to make the dtor virtual as well.
There is no safety concern associated with virtual function inside a template class. It is as good as, having a virtual function inside a normal class.

How to define member function coming from non-template base class

I have a non-templated abstract base class. How do I define the pure virtual function outside derived class?
#include <iostream>
class base {
public:
virtual void func() = 0;
};
template<typename T>
class der : public base{
};
template<typename T>
void der<T>::func()
{
std::cout<<"In Der";
}
The following error comes up:
template.cpp:13: error: no ‘void der<T>::func()’ member function declared in class ‘der<T>’
template.cpp:13: error: template definition of non-template ‘void der<T>::func()’
Declare the member function.
template<typename T>
class der : public base{
public:
void func();
};
There's no automatic declaration of member functions that you may or may not wish to override in a derived class - you have to explicitly declare and define these. Whether the derived class is implemented as a template or not doesn't matter for this.
You must declare the virtual override in the derived class definition.
template <typename T>
class der : public base {
public:
virtual void func();
};
This will work:
#include <iostream>
class base {
public:
virtual void func() = 0;
};
template<typename T>
class der : public base{
public:
void func()
{
std::cout<<"In Der";
}
};
It has been recommended to me to drop function definitions straight into templates when possible, except for specializations.
edit: 'inline' was not the best choice of word here