C++ circular dependencies with nested class - c++

I'm trying to generate header files of classes I'm reconstructing from what I disassembled with IDA. However I'm getting compile errors due to circular dependencies. For regular classes I solved it by declaring them in a separate file I include as a first. The thing is I cannot declare inner class without definition of an outer class which is the problem.
An example class structure:
Class A:
#include "B.h"
class A {
public:
class Nested {
public:
void foo(B::Nested &foo);
};
};
Class B:
#include "A.h"
class B {
public:
class Nested {
public:
void foo(A::Nested &foo);
};
};

You can forward declare the Nesteds in A and B, and define them afterward.
a.h
class A {
public:
class Nested;
};
B.h
class B {
public:
class Nested;
};
Nested.h
#include "A.h"
#include "B.h"
class A::Nested {
public:
void foo(B::Nested &foo);
};
class B::Nested {
public:
void foo(A::Nested &foo);
};

Use templates.
class A {
public:
class Nested {
public:
template<class B>
void foo(typename B::Nested &fo);
};
};
class B {
public:
class Nested {
public:
template<class A>
void foo(typename A::Nested &fo);
};
};
template<>
void A::Nested::foo<B>(B::Nested &fo){
}
template<>
void B::Nested::foo<A>(A::Nested &fo){
}
e.g. (Here the template has been moved up so the type doesn't have to be specified with each function call.)
#include <iostream>
class A {
public:
template <class B>
class Nested {
public:
std::string name() const { return "a"; }
void foo(typename B:: template Nested<A> &fo);
};
};
class B {
public:
template <class A>
class Nested {
public:
std::string name() const { return "b"; }
void foo(typename A:: template Nested<B> &fo);
};
};
template<>
void A::Nested<B>::foo(B::Nested<A> &fo){
std::cout << "A::Nested " << fo.name() << '\n';
}
template<>
void B::Nested<A>::foo(A::Nested<B> &fo){
std::cout << "B::Nested " << fo.name() << '\n';
}
int main()
{
A::Nested<B> a;
B::Nested<A> b;
a.foo(b);
b.foo(a);
}

When a compiler reads your file it is expecting declared entities.
You can forward declare the class but you would be missing the Nested Parameter type.
What you can do is to have a third class which breaks the circular dependency and inherits to the your nested classes:
class NestedBase {
};
Now use this base in your A nested class:
#include "NestedBase.h"
class A {
public:
class Nested : public NestedBase {
public:
void foo(NestedBase &foo);
};
};
And in your B nested class as well:
#include "NestedBase.h"
class B {
public:
class Nested : public NestedBase {
public:
void foo(NestedBase &foo);
};
};
Now with dynamic_cast in your method implementations you can convert them to your desired types and access whatever you declared in your Nested Classes.
#include "A.h"
#include "B.h"
B::Nested::foo(NestedBase &foo)
{
auto &fooA = dynamic_cast<A::Nested&>(foo);
...
}

Related

Simplifying API of classes extending each other by CRTP

I want to write class that extends multiple classes by (CRTP).
I can only get Extension<Base<Extension>> my_object; to work.
The api that I want is: Extension<Base> my_object;
How to make this api work?
Thanks.
Test (code is also at godbolt.org):
#include <iostream>
template <template<typename...> class Extension>
class Base1 : public Extension<Base1<Extension>> {
public:
static void beep() { std::cout << "Base1 "; }
};
template <class Plugin>
class Extension1 {
public:
Extension1() : plugin_(static_cast<Plugin*>(this)) {}
void beep() {
plugin_->beep();
std::cout << "Extension1\n";
}
private:
Plugin* plugin_;
};
template <template<typename...> class Plugin>
class Extension2 {
public:
Extension2() : plugin_(static_cast<Plugin<Extension2>*>(this)) {}
void beep() {
plugin_->beep();
std::cout << "Extension2\n";
}
private:
Plugin<Extension2>* plugin_;
};
int main() {
// This works.
Extension1<Base1<Extension1>>b;
b.beep();
// This doesn't work.
Extension2<Base1> c;
c.beep();
return 0;
}
One problem is that the template parameter to Extension2 does not match the signature that Base1 has. Another is that Extension2 does not match the parameter type expected by Base1.
If you change the definition of Extension2 to propertly accept Base1, it itself is still not a candidate to be passed to Base1. You can workaround that with an inner template class that does match what Base1 expects. This inner class would look a lot like Extension1.
template <template<template<typename...> class> class Plugin>
class Extension2 {
template <class P>
struct Inner {
Inner () : plugin_(static_cast<P *>(this)) {}
void beep() { plugin_->beep(); }
private:
P* plugin_;
};
public:
Extension2() {}
void beep() {
plugin_.beep();
std::cout << "Extension2\n";
}
private:
Inner<Plugin<Inner>> plugin_;
};

Circular dependency with template function

I have a class A with the following declaration (A.h file):
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#endif
and a class B deriving from that class (B.h file):
#ifndef __B_DEFINED__
#define __B_DEFINED__
#include <iostream>
#include "A.h"
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
So far, so good. My issue is that the function A::doThat() uses B::doThis():
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
Usually, the circular dependency would not be an issue because I would just define A::doThat() in the .cpp file. In my case however, doThat is a template function so I can't do that.
Here are the solutions I have envisioned so far:
Defining the template function A::doThat() in a .cpp file. The issue with that is that I need to instantiate explicitly all the calls with various template arguments (there might be many in the real case).
After the declaration of the A class in A.h, add #include "B.h" and then define the A::doThat() function. This works fine in visual studio but g++ does not like it.
Is there a neat way to solve this problem?
EDIT: In the real case, there is not just one child class B, but several (B, C, D, etc.) The function A::doThat() depends on all of them. The function B::doThis() is also templated.
A default template parameter for the B class could work:
#include <iostream>
// include A.h
class B;
class A
{
public:
template<typename T, typename U = B> inline void doThat() const
{
U b; b.doThis();
}
};
// include B.h
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
// main
int main()
{
A a;
a.doThat<int>();
}
Usually the best way to allow a parent to call a child function is to declare the function as a pure virtual function in the parent and override it in the children.
#include <iostream>
class A
{
public:
virtual ~A() = default;
template<typename T> inline void doThat() const
{
// do some other stuff
doThis();
}
virtual void doThis() const = 0; // pure virtual function
};
class B: public A
{
public:
void doThis() const override
{
std::cout << "do this!" << std::endl;
}
};
int main()
{
B b;
A* ap = &b;
ap->doThat<int>();
}
The following does work with g++:
File A.h:
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#include "B.h"
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
#endif
File B.h:
#include <iostream>
#include "A.h"
// We check for the include guard and set it AFTER the inclusion of A.h
// to make sure that B.h is completely included from A.h again.
// Otherwise the definition of A::doThat() would cause a compiler error
// when a program includes B.h without having included A.h before.
#ifndef __B_DEFINED__
#define __B_DEFINED__
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
File test_A.cpp:
// In this test case we directly include and use only A.
#include "A.h"
#include "A.h" // We test whether multiple inclusion causes trouble.
int main() {
A a;
a.doThat<int>();
}
File test_B.cpp:
// In this test case we directly include and use only B.
#include "B.h"
#include "B.h" // We test whether multiple inclusion causes trouble.
int main() {
B b;
b.doThat<int>();
b.doThis();
}
Alternative Idea:
I do not know whether you (or some coding conventions) insist on separate header files for each class, but if not the following should work:
You can put the definitions of class A and class B and of the member function template A::doThat<typename>() (in this order) together in one header file AandB.h (or whatever name you like).
This cries for polymorphism. There are two options using polymorphism:
Dynamic polymorphism, i.e. make A an abstract base class and call doThis() virtually:
struct A
{
virtual void do_this() const = 0;
template<typename T>
void doThat() const { doThis(); }
};
struct B : A
{
void doThis() const override { /* ... */ }
};
Of course, this only works if doThis() is not templated. If you need that, you could use
Static polymorphism, i.e. CRTP, when
template<typename Derived>
struct A
{
template<typename T>
void doThat() const { static_cast<const Derived*>(this)->template doThis<T>(); }
};
struct B : A<B>
{
template<typename T>
void doThis() const { /* ... */ }
};
If (as in your example code) B::doThis() is not called for the same object, but for some temporary, you could
template<typename typeB>
struct A
{
template<typename T>
void doThat() const { typeB b; b.template doThis<T>(); }
};

Is that possible to know all the name of derived classes?

Suppose we have a base class and a bunch of derived classes. Is there any way or mechanism to know all the derived class names programmatically?
Maybe reflection is a good idea, but it's not available on C++. I suppose there will be some kind of template that can finish this job during compilation.
class Base{
public:
virtual void print(){
// This function should print all the names of derived class.
}
virtual Base* getInstance(string class_name){
// This function should return an instance related to the class name.
}
};
class Derived_1 : public Base{ // Suppose we have 100 Derived_X classes,
// so we don't want to add its name to a list manually.
};
int main(){
Base base;
base.print(); // This should print the name of all the derived class.
base.getInstance("Derived_1"); // This should return an instance of Derived_1
return 0;
}
This solution is based on the fact that it seems you are actually looking for a factory. It uses a small macro to ease classes registration, hope you don't care about it.
factory.h
#ifndef __FACTORY_H__
#define __FACTORY_H__
#include <map>
#include <functional>
#include <string>
#include <iostream>
template<class B>
class Factory {
std::map<std::string, std::function<B*()>> s_creators;
public:
static Factory<B>& getInstance() {
static Factory<B> s_instance;
return s_instance;
}
template<class T>
void registerClass(const std::string& name) {
s_creators.insert({name, []() -> B* { return new T(); }});
}
B* create(const std::string& name) {
const auto it = s_creators.find(name);
if (it == s_creators.end()) return nullptr; // not a derived class
return (it->second)();
}
void printRegisteredClasses() {
for (const auto &creator : s_creators) {
std::cout << creator.first << '\n';
}
}
};
#define FACTORY(Class) Factory<Class>::getInstance()
template<class B, class T>
class Creator {
public:
explicit Creator(const std::string& name) {
FACTORY(B).registerClass<T>(name);
}
};
#define REGISTER(base_class, derived_class) \
Creator<base_class, derived_class> s_##derived_class##Creator(#derived_class);
#endif
example.cpp
#include "factory.h"
#include <memory>
class Base {
public:
virtual void printName() const { std::cout << "Base\n"; }
};
class Derived1 : public Base {
public:
virtual void printName() const override { std::cout << "Derived1\n"; }
};
REGISTER(Base, Derived1);
class Derived2 : public Base {
public:
virtual void printName() const override { std::cout << "Derived2\n"; }
};
REGISTER(Base, Derived2);
int main() {
std::cout << "Registered classes:" << std::endl;
FACTORY(Base).printRegisteredClasses();
std::cout << "---" << std::endl;
std::unique_ptr<Base> derived1(FACTORY(Base).create("Derived1"));
derived1->printName();
return 0;
}
Note: requires C++11.
For the getInstance you can declare it a template (needs C++14). To get all the names of the derived classes in the program you probably have to resort to some preprocessor hack.
#include <type_traits>
class Base
{
public:
virtual ~Base () = default;
template < typename T,
typename = std::enable_if_t<std::is_base_of<Base, T>::value, void>
>
T getInstance() { return T{}; }
};
class Derived : public Base {};
class NotDerived {};
int main(){
Base base;
base.getInstance<Derived>();
// error: no matching member function for call to 'getInstance'
//base.getInstance<NotDerived>();
}
Regarding the name of the derived classes, I propose a solution based on a BaseList class/struct, with a static std::set (or other container) of names, a template Base class/struct, that inherit from BaseList and whose template parameter is the derived class (CRTP style) and (to semplify the construction of the derived classes/struct, a C-style macro (I know... macros are distilled evil... but sometimes...) to create the declaration of the derived classes/structs with a necessary static method, that declare the name of the derived class/struct, and a member (that activate the registration of the name).
The following is a full example (unfortunately is a C++11 one)
#include <set>
#include <string>
#include <iostream>
struct BaseList
{
static std::set<std::string> const & derList (std::string const & dn)
{
static std::set<std::string> dl;
if ( dn.size() )
dl.insert(dn);
return dl;
}
static void print ()
{
std::cout << "derived names: ";
for ( auto const & dn : derList("") )
std::cout << dn << ", ";
std::cout << std::endl;
}
};
template <typename Der>
struct Base : public BaseList
{
static std::size_t setNameInList ()
{ return derList(Der::name()).size(); }
static std::size_t id;
};
template <typename Der>
std::size_t Base<Der>::id = setNameInList();
#define setDerived(nameDer) \
struct nameDer : public Base<nameDer>\
{ \
std::size_t idc { id }; \
static std::string name () \
{ return #nameDer; }
setDerived(Derived_1)
// other elements
};
setDerived(Derived_2)
// other elements
};
setDerived(Derived_3)
// other elements
};
int main()
{
BaseList::print();
}
Regarding the getInstance() problem, the only solution that I can imagine is the same solution proposed by Enry Menke (+1), so I suggest that you get the instance through a template type parameter.

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

C++ design pattern - member-only class

I want a class that can only be instantiated as a member of another class.
Id est:
class A
{
public:
A() :
member_()
{};
void letBSayHi() { member_.sayHi(); }
private:
B member_;
};
class B
{
public:
void sayHi() { printf("hola!"); }
};
thus:
A alpha; // valid
alpha.letBSayHi(); // # hola!
B beta; // invalid
beta.sayHi(); // impossible
The singleton pattern obviously wouldn't work, as I want one instance of class B for every instance of class A. But any instantiation of class B other than as a class A-member should be prohibited.
Make B a private nested class of A:
class A {
public:
void letBSayHi() { member_.sayHi(); }
private:
class B {
public:
void sayHi() { std::cout << "hola!"; }
};
B member_;
};
Addendum re: comment: The implementation can be separated from the declaration like this:
Header:
class A {
public:
void letBSayHi();
private:
class B {
public:
void sayHi();
};
B member_;
};
Source file:
void A::letBSayHi() { member_.sayHi(); }
void A::B::sayHi() { std::cout << "hola!\n"; }
// ^^^^-- interesting part here
Well, if you want to include, why not?
class A {
#include "B.hpp"
...
};