Refer to derivative function - c++

I have a base class and a few derivative. I have to 'register' some static function from each of them. Here is the example:
class Base
{
// Some interface...
};
class Der1 : Base
{
static void Do();
};
class Der2 : Base
{
static void Do();
};
void processStatic()
{
SomeFunc(Der1::Do);
SomeFunc(Der2::Do);
}
As you see, SomeFunc receives function pointer. I want to do that automatically with each new derivative class, is it possible? Maybe, predefine static function in Base class and register it there. But I think it's impossible, yes?
Maybe, this will be more easier to understand what do I want:
class Der1 : Base
{
Der1() { SomeFunc(Der1::Do); }
static void Do();
};
class Der2 : Base
{
Der2() { SomeFunc(Der2::Do); }
static void Do();
};

EDIT: Completely replacing previous answer due to clarified requirements.
You could use the CRTP to declare a specialized base class that does nothing more than call your registration function:
#include <iostream>
void SomeFunc(void(*fp)()) {
(*fp)();
};
template <class D>
struct ExtraBass {
ExtraBass() {
static bool once;
if(!once)
SomeFunc(D::Do);
once = true;
}
};
struct Bass {
};
struct Drive : Bass, ExtraBass<Drive> {
static void Do() { std::cout << "Drive::Do\n"; }
};
struct Deride : Bass , ExtraBass<Deride> {
static void Do() { std::cout << "Deride::Do\n"; }
};
int main() {
Drive d1;
Deride d2;
Deride d3;
}

This is not an easy thing to do in C++, but I'm not saying it's impossible. If all you need is a list of subclass names, these answers might help:
Somehow register my classes in a list
c++ List of classes without initializing them for use of static functions
Seems either macro magic or boost mpl is your tool of choice.

I just wondering, if you did something like
void SomeFunc(void (*doFunc)())
{
doFunc();
}
template <class T> int Register()
{
SomeFunc(T::Do);
return 0;
}
template <class T> class Base
{
static int _i;
};
template <class T> int Base<T>::_i = Register<T>();
class Derived : Base<Derived>
{
public:
static void Do() { }
};

Related

C++ - Pushing variadic template class object into vector

class Base
{
public:
virtual void foo() = 0;
};
class A : public Base
{
public:
void foo() override { std::cout << "A\n"; }
};
class B : public Base
{
public:
void foo() override { std::cout << "B\n"; }
};
class Registry
{
public:
static Registry& instance()
{
static Registry s_instance;
return s_instance;
}
void register_foo(Base* foo)
{
m_vec.emplace_back(foo);
}
private:
std::vector<Base*> m_vec;
};
template<typename ... T>
class Foo : public T...
{
public:
Foo()
{
Registry::instance().register_foo(this);
}
void test() { (T::foo(), ...); }
};
int main()
{
auto f1 = std::make_unique<Foo<A, B>>();
auto f2 = std::make_unique<Foo<A>>();
f1->test();
f2->test();
}
As you can see I have a Base class, class A and class B.
A and B inherit from Base.
Class Foo is a template class, which is with a variadic template.
The idea is to be able to pass class A and class B into Foo.
Then this Foo is registered in the Registry class / pushed into a vector.
The problem is the following - as you can see I can have both Foo<A> and Foo<A, B>, or Foo<B, A>.
How can I have such a vector which can accept all possible types of Foo?
How about a simple common base class?
class FooBase {
public:
virtual ~FooBase() {}
virtual void test() = 0;
};
template<typename... T>
class Foo : public FooBase, public T...
{
public:
Foo() { }
void test() override { (T::foo(), ...); }
};
int main()
{
auto f1 = std::make_unique<Foo<A, B>>();
auto f2 = std::make_unique<Foo<A>>();
std::vector<std::unique_ptr<FooBase>> foos;
foos.push_back(std::move(f1));
foos.push_back(std::move(f2));
}
A std::vector holds one type of objects. You cannot put objects of different types into the same vector (and objects created from a template with different template arguments are different types).
One option (I'd not recommend it) is having a vector that holds instances of std::any) - works, but cumbersome and inefficient to work with. Another option is a vector of pointers to a common base class and taking advantage of polymorphism. A third option is simply having sepperate vectors for each type of object.

If I create a template class, than other classes where I send reference (pointer) to that class must be templated?

Let say I've this code with a EnvelopeMultiPoints class template:
#include <iostream>
#include <vector>
class EnvelopeMultiPointsBase
{
// base
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
void Process() {
std::cout << "process: " << mNumPoints << std::endl;
}
};
class Pitch : public EnvelopeMultiPoints<Pitch> { };
template<typename T>
unsigned int EnvelopeMultiPoints<T>::mNumPoints = 5;
class Container
{
public:
EnvelopeMultiPointsBase *pAssociatedEnvelope;
Container(EnvelopeMultiPointsBase *associatedEnvelope) : pAssociatedEnvelope(associatedEnvelope) { }
~Container() { }
void Process();
private:
};
int main()
{
EnvelopeMultiPoints<Pitch> pitch;
Container container(&pitch);
container.pAssociatedEnvelope->Process();
}
And I want to pass to the Container any kind of "EnvelopeMultiPoints" types (a generic "pointer"), so later I can access to its own method (in my case, Process()).
Does it means that also Container must be templated? (which is huge in my real scenario; lot of works to transform all of its methods in template, translate header/cpp, and such).
Or is there a trick that I'm missing?
In few words: let say that I want to pass to Container EnvelopeMultiPoints<Pitch>, and than execute Process(). Later, I want to pass EnvelopeMultiPoints<Volume> instead, and than execute Process(). And so on. Is there a way to do this without converting also Container to a template?
The technique you need is called dynamic polymorphism
that is implemented in C++ by virtual functions.
Illustrating using your code:
class EnvelopeMultiPointsBase
{
public:
// Abstract base, no actual implementation
virtual void Process() = 0;
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
// Some specific implementation.
virtual void Process() override
{
std::cout << "process: " << mNumPoints << std::endl;
}
};
class Pitch : public EnvelopeMultiPoints<Pitch>
{
};
To call the Process function of the base class, you have to define it in the base class. You can move the implementation to templated child classes:
class EnvelopeMultiPointsBase
{
private:
virtual void ProcessImpl() = 0;
public:
void Process() {
//potential common code...
ProcessImpl();
//more potential common code...
}
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
private:
void ProcessImpl() {
std::cout << "process" << std::endl;
}
};

Iterate over different CRTP Derived class methods

In an example below I have a pretty typical CRTP example, two different derived classes that both have a method bar. The base class has a method foo which just forwards to some derived bar method
#include <iostream>
template<typename Derived>
class Base {
public:
void foo() {
static_cast<Derived*>(this)->bar();
}
};
class DerivedA : public Base<DerivedA> {
public:
void bar() {
::std::cout << "A\n";
}
};
class DerivedB : public Base<DerivedB> {
public:
void bar() {
::std::cout << "B\n";
}
};
int main() {
DerivedA a;
DerivedB b;
a.foo();
b.foo();
}
It doesn't seem like I can have an array / vector / etc. of the base class because it would have to have a type along the lines of Base<T> where T is different
Is there some kind of convention without virtual for being able to iterate over different derived classes assuming they all have the same method (bar in this case)?
You can use Boost.Variant. For example:
typedef boost::variant<DerivedA, DerivedB> Derived;
struct BarCaller : public boost::static_visitor<void> {
template <class T>
void operator()(T& obj) {
obj.bar();
}
};
int main() {
std::vector<Derived> vec{DerivedA(), DerivedB(), DerivedA()};
BarCaller bar;
for (Derived& obj : vec) {
obj.apply_visitor(bar);
}
}
This lets you store heterogeneous types in a vector or other STL container (by using a "discriminated union"), and lets you call a specific function on all of them regardless of their not having a common ancestor or any virtual methods.
It doesn't seem like I can have an array / vector / etc. of the base class because it would have to have a type along the lines of Base<T> where T is different.
You can have a base class of Base<T> for all T, then, you can have a list/vector/array of pointers to the base class, if that works for you.
struct BaseOne
{
virtual void foo() = 0;
virtual ~BaseOne() {}
};
template<typename Derived>
class Base : struct BaseOne {
public:
void foo() {
static_cast<Derived*>(this)->bar();
}
};
and then,
int main() {
std::vector<BaseOne*> v {new DerivedA, new DerivedB };
for ( auto item : v )
item->bar();
for ( auto item : v )
delete item;
}
Is there some kind of convention without virtual for being able to iterate over different derived classes assuming they all have the same method (bar in this case)?
No, there isn't.
As per now, variant has became part of the C++17 standard and the solution to the problem can be solved by std::variant and std::visit as follows.
The template class in the example is Interface<> and use the CRTP idiom to force derived class to implement helloImpl():
#include <iostream>
#include <vector>
#include <variant>
template<typename Implementer>
struct Interface {
void hello() const {
static_cast<Implementer const *>(this)->helloImpl();
}
};
A couple of class examples with different implementations of helloImpl()
struct Hello1 : public Interface<Hello1> {
void helloImpl() const {
std::cout << "Hello1" << std::endl;
}
};
struct Hello2 : public Interface<Hello2> {
void helloImpl() const {
std::cout << "Hello2" << std::endl;
}
};
And here is how to use it to store data in a vector<> container and its traversal:
int main() {
using var_t = std::variant<Hello1, Hello2>;
std::vector<var_t> items{Hello1(), Hello1(), Hello2()};
for(auto &item: items) {
std::visit([](auto &&arg) {
arg.hello();
}, item);
}
return 0;
}

How do I retrieve the type of the base class in C++?

For this particular project, I am not able to use C++11 features (e.g. decltype) because the compiler does not yet support them. I need to be able to provide the current class as a template parameter, preferably within a macro without an argument (see below), without dressing up the class declaration or hiding curly braces, etc.
class Foo: private Bar<Foo> {
MAGIC //expands to using Bar<Foo>::Baz; and some others
public:
void otherFunction();
//... the rest of the class
};
Ideally, I'd like this to work very much like Qt's Q_OBJECT macro, but without introducing another pre-compile step and associated generated classes. typeid might be useful at runtime, but my goal is to accomplish all of this at build.
How do I write the MAGIC macro so that I don't need to repeat the class name each time?
What about:
template<typename T>
class Base
{
protected:
typedef Base<T> MagicBaseType;
namespace Baz { }
};
class Derived1 : private Base<Derived1>
{
using MagicBaseType::Baz;
}
class Derived1 : private Base<Derived2>
{
using MagicBaseType::Baz;
}
or, if you can't modify the Base definition, using templates and multiple inheritance
template<typename T>
class Base
{
protected:
namespace Baz { }
};
template<typename T>
class DerivedTemplate : public T
{
protected:
typedef typename T BaseType;
}
class Derived : public Base<Derived>, public DerivedTemplate<Base<Derived>>
{
using BaseType::Baz;
}
I don't think there is any language supported mechanism to extract the base type from a class. You can use:
Option 1
class Foo: private Bar<Foo> {
#define BASE_TYPE Bar<Foo>
// Use BASE_TYPE in MAGIC
MAGIC //expands to using Bar<Foo>::Baz; and some others
#undef BASE_TYPE
public:
void otherFunction();
//... the rest of the class
};
Option 2
class Foo: private Bar<Foo> {
typedef Bar<Foo> BASE_TYPE;
// Use BASE_TYPE in MAGIC
MAGIC //expands to using Bar<Foo>::Baz; and some others
public:
void otherFunction();
//... the rest of the class
};
If you really don't care about formatting or writing a maintenance headache you can do this without repeating the type by having the macro take the type argument:
#define MAGIC(BASE) \
BASE { \
using BASE::baz;
class Sub : private MAGIC(Base<Foo>)
public:
void otherFunction();
};
but this makes me feel pretty bad about myself
You could use a "proxy"(?) struct for Building up the inheritance:
template <typename S>
struct Base : public S{ //always public, access is restricted by inheriting Base properly
using super = S;
};
Usage would be as follows:
#include <iostream>
template <typename S>
struct Base : public S {
using super = S;
};
template <typename T>
class Bar
{
public:
virtual void f() { std::cout << "Bar" << std::endl; }
};
class Foo : private Base<Bar<int>>
{
public:
virtual void f()
{
std::cout << "Foo";
super::f(); //Calls Bar<int>::f()
}
};
class Fii : private Base<Foo>
{
public:
virtual void f()
{
std::cout << "Fii";
super::f(); //Calls Foo::f()
}
};
int main()
{
Fii fii;
fii.f(); //Print "FiiFooBar"
return 0;
}

looking for solution of c++ member function override (non virtual)

I've two classes:
struct A {
template <typename T>
void print(T& t){
// do sth specific for A
}
};
struct B : A {
template <typename T>
void print(T& t){
// do sth specific for B
}
};
In such case, the more general Base class with virtual functions (which A and B both inherit from) cannot be compiled, since there is no virtual for template. As I try to delegate generally all A or B objects under same "interface", does anyone has the idea to resolve such problem? Thank you in advance.
Sincerely,
Jun
You can think about using using CRTP.
template<typename Derived>
struct Base {
template <typename T>
void print(T& t){
static_cast<Derived*>(this)->print(t);
}
};
struct A : Base<A> {
// template print
};
struct B : Base<B> {
// template print
};
Example Usage:
template<typename T, typename ARG>
void foo (Base<T>* p, ARG &a)
{
p->print(a);
}
This method will be called as,
foo(pA, i); // pA is A*, i is int
foo(pB, d); // pB is B*, d is double
Here is another demo code.
Using a proxy class to get B's method
class A {
public:
friend class CProxyB;
virtual CProxyB* GetCProxyB() = 0;
};
class B;
class CProxyB
{
public:
CProxyB(B* b){mb = b;}
template <typename T>
void printB(T& t)
{
mb->print(t);
}
B* mb;
};
class B:public A {
public:
virtual CProxyB* GetCProxyB(){return new CProxyB(this);};
template <typename T>
void print(T& t){
printf("OK!!!!!\n");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* a = new B;
CProxyB* pb = a->GetCProxyB();
int t = 0;
pb->printB(t);
return 0;
}
Two options:
Option one: Virtualize the method where if the user does not provide an implementation, the Base class' is used.
template <typename T>
struct A {
virtual void print(T& t);
};
template <typename T>
void A::print(T& t) {
// do sth specific for A
}
template <typename T>
struct B : A {
virtual void print(T& t);
};
void B::print(T& t) {
// do sth specific for B
}
Option two: Abstract the method where if the user does not provide an implementation, the code will not compile.
template <typename T>
struct A {
virtual void print(T& t)=0;
};
template <typename T>
struct B : A {
virtual void print(T& t){
// do sth specific for B
}
};
template <typename T>
void B::print(T& t){
// do sth specific for B
}
Other than the above mentioned, if you do not make them virtual, the Derived class will Shadow the Base class method and that is most certainly not what you intended. Hence, impossible.
my question is how to use single pointer to different A or B objects.
You can do this without virtual functions per-se. But all you will really be doing is writing an implementation of a V-table and virtual functions.
If I were going to manually implement virtual functions, I would base it all on a Boost.Variant object. The variant would effectively hold the member data for each class. To call a function, you use a variant visitor functor. Each "virtual function" would have its own visitor functor, which would have different overloads of operator() for each of the possible types within the variant.
So you might have this:
typedef boost::variant<StructA, StructB, StructC> VirtualClass;
You could store any one of those objects in the variant. You would call a "virtual function" on the object like this:
VirtualClass someObject(StructA());
boost::apply_visitor(FunctorA(), someObject);
The class FunctorA is your virtual function implementation. It is a visitor, defined like this:
class FunctorA : public boost::static_visitor<>
{
void operator()(StructA &arg){
//Do something for StructA
}
void operator()(StructB &arg){
//Do something for StructB
}
void operator()(StructC &arg){
//Do something for StructC
}
}
Visitors can have return values, which are returned by apply_visitor. They can take arguments, by storing the arguments as members of the visitor class. And so forth.
Best of all, if you ever change your variant type, to add new "derived classes", you will get compiler errors for any functors that don't have overloads for the new types.
But to be honest, you should just be using virtual functions.
By using CRTP(Curiously recurring template pattern), you can achieve static polymorphsim without virtual.
#include <iostream>
using namespace std;
#define MSG(msg) cout << msg << endl;
template<class Derived>
class Base{
public:
void print()
{
static_cast<Derived*>(this)->print();
}
};
class Derived1 : public Base<Derived1>
{
public:
void print()
{
MSG("Derived 1::print");
}
};
class Derived2 : public Base<Derived2>
{
public:
void print()
{
MSG("Derived 2::print");
}
};
template<class T>
void callme(Base<T>& p)
{
p.print();
}
int main()
{
Base<Derived1> p1;
Base<Derived2> p2;
callme(p1);
callme(p2);
system("pause");
return 0;
}
//Result :
//Derived 1::print
//Derived 2::print