I have some code in C++ where I use a macro for the class definitions. Doxygen fails to resolve this properly.
I am using Doxygen 1.9.3.
The configuration file differences to default are:
EXTENSION_MAPPING = h=C++ cpp=C++
EXTRACT_ANON_NSPACES = YES
SHOW_GROUPED_MEMB_INC = yes
FILE_PATTERNS = *.c *.cpp *.h
RECURSIVE = YES
CLANG_ASSISTED_PARSING = YES
MACRO_EXPANSION = YES
The code example consists of three files:
Interfaces/IMetaObject.h:
class IMetaObject
{
virtual ~IMetaObject() {};
virtual const char* GetType() const = 0;
virtual const std::vector<const char *>& GetInterfaces() const = 0;
virtual const bool IsInterface(const char *) const = 0;
};
Interfaces/MetaObject.h:
#include "IMetaObject.h"
#define MetaObjectClass(className, interfaceName) \
namespace kia{ constexpr char class_##className[] = #className; } \
class className : public MetaObject<kia::class_##className>, virtual public interfaceName \
{ \
AddInterface(MetaObject, interfaceName::Name)
template<const char* type_name>
class MetaObject : public virtual IMetaObject
{
public:
MetaObject() {}
virtual ~MetaObject() {};
virtual const char* GetType() const override
{
return NULL;
}
virtual const std::vector<const char*>& GetInterfaces() const override
{
return _interfaces;
}
virtual const bool IsInterface(const char* interface) const override
{
return true;
}
};
and Modules/Modul.h:
#include "MetaObject.h"
#include "Instances.h"
MetaObjectClass(Modul, IModul)
public:
Modul(){}
virtual ~Modul()
{
}
};
The class Modul is not recognized by doxygen, which is obvious in the class hierarchy diagram.
When I move the code from the subdirectories to the main directory, everything works. This is good for a workaround, but - how can I tell doxygen to resolve the macros properly in case of subdirectories?
Related
On a simple embedded platform I have no RTTI available but I want to use c++ advantages like inheritance for a class hierarchy like the provided sample. At the moment I'm using the following code snipped to simulate a dynamic cast. To simplify this discussion I ported the code to a simple main.cpp. I used the mingw compiler for testing my sample. The code is working as expected but seams not ideal. I'm not searching for a generic dynamic cast replacement solution considering all aspects. Is there any way to implement this cast with less effort?
class I_BC
{
public:
virtual ~I_BC() {}
virtual int getI_BC() = 0;
};
class I_C
{
public:
virtual ~I_C() {}
virtual int getI_C() = 0;
};
class A
{
public:
virtual ~A() {}
int xx() {return 1;}
template <typename T>
T* cast() { return nullptr;}
protected:
virtual I_BC* cast2BC() {return nullptr;}
virtual I_C* cast2C() {return nullptr;}
};
template <>
I_BC* A::cast<I_BC>() {return this->cast2BC();}
template <>
I_C* A::cast<I_C>() {return this->cast2C();}
class B : public A, public I_BC
{
public:
int getI_BC() override { return 0xB000000C;}
int bar() {return 2;}
protected:
I_BC* cast2BC() override {return this;}
};
class C : public A, public I_BC, public I_C
{
public:
int foo() {return 3;}
int getI_C() override { return 0xC000000C;}
int getI_BC() override { return 0xC00000BC;}
protected:
I_BC* cast2BC() override {return this;}
I_C* cast2C() override {return this;}
};
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
A* a = new B();
// Ok I know that B implement I_BC interface so cast it now
I_BC* bc = a->cast<I_BC>();
cout << "Res : 0x" << hex << bc->getI_BC() << endl;
}
Here’s a custom RTTI implementation that uses macros to reduce boilerplate code:
https://www.axelmenzel.de/articles/rtti
I'm trying to create a base class defining an interface for derived classes - say a simple audio wrapper class.
class AudioStreamBase
{
public:
virtual
~AudioStreamBase(void);
virtual void
open(const void * settings) = 0;
virtual void
start(void) = 0;
virtual void
stop(bool force) = 0;
virtual void
close(void) = 0;
virtual int
recover(int err) = 0;
virtual int
readFrames(void * buffer) = 0;
virtual int
writeFrames(void * buffer) = 0;
virtual void
printConfig(void) = 0;
};
As different implementations may accept different configuration parameters in Linux/Win/embedded system, I've defined the input parameter for open() as:
const void * settings
One possible implementation could be:
struct settingsA
{
int param1;
int param2;
...
};
class AudioStreamA : public AudioStreamBase
{
public:
...
void open(const void* settings) { settingsA * s = (settingsA) settings; ...};
...
}
However, this doesn't seem to be very C++ - I'm used to C a lot and I'm starting with C++ after several years again. Is there a better solution? I was thinking about templating the class or the method, but as the type is a struct, I won't be able to access the parameters. And building a complex struct construct to read it's parameters seems obscure for something simple like accessing few parameters in a struct.
You could use the CRTP to inject the derived class into the base. Then you could define a traits helper to define e.g. which settings have to be used for some derived class. Admittedly, a bit verbose but now your code is type-safe.
If you need the base class to be non-template, you could pull out everything except the open into a non-template top base class.
class AudioStreamA;
struct settingsA;
template<class T>
struct AudioStreamTraits;
template<>
struct AudioStreamTraits<AudioStreamA> {
using Settings = settingsA;
};
template<class Derived>
class AudioStreamBase
{
protected:
using StreamTraits = AudioStreamTraits<Derived>;
using Settings = typename StreamTraits::Settings;
public:
virtual
~AudioStreamBase() = default;
virtual void
open(const Settings& settings) = 0;
//...
};
struct settingsA
{
int param1;
int param2;
};
class AudioStreamA : public AudioStreamBase<AudioStreamA>
{
using Base = AudioStreamBase<AudioStreamA>;
using Base::Settings;
public:
void open(const Settings& settings) override { };
};
int main() {
AudioStreamA s;
settingsA settings;
s.open(settings);
return 0;
}
See code example here
However, if you only need the settings in the derived class, you could simply replace the open by a constructor in the derived class:
class AudioStreamBase
{
public:
virtual
~AudioStreamBase() = default;
// ....
};
struct settingsA
{
int param1;
int param2;
};
class AudioStreamA : public AudioStreamBase
{
public:
AudioStreamA(const settingsA& settings) { } ;
};
Let's say I have this class
struct IDebug {
virtual void print(std::ostream&) const = 0;
};
and the prints should follow some format defined for each class implementing IDebug.
the format is static in the sense that for a certain implementation will always have the same format and that I want the format to be used regardless of whether I have any instance of the class (for example at program initialization)
so I added a:
static std::string format();
to each of the implementing class. ugly (because it's not forced by the interface) but I could live with that
now I wanted to add some validation in the interface level that the actual print() is following the format this class defines. in order to do that I had to make a modification:
struct IDebug {
void print(std::ostream& o) const { // no longer virtual
auto format = format_impl();
// preprocess using format
print_impl(o);
// postprocess using format
}
protected:
virtual void print_impl(std::ostream& o) const = 0;
virtual std::string format_impl() const = 0;
};
and each of the implementing classes now have the exact same line of code:
std::string format_impl() const override { return format(); }
struct MooDebug : public IDebug {
// rest of the code
static std::string format() { return "whatever"; } // this was already here. sadly the interface couldn't force it
std::string format_impl() const override { return format(); } // all implementing classes are repeating this exact line
};
I'm looking for advice how to avoid it or make it better.
You could make use of some CRTP like class to create a base class that does what you want:
struct MooDebug : DebugHelper<MooDebug>
{
static std::string format() { return "whatever"; }
};
template<typename T>
struct DebugHelper : IDebug
{
std::string format_impl() const override { return T::format(); }
};
Note that in CRTP you actually cast your this pointer to T& and call a method that way.
Alternative in C++17 (haven't tested this), you can pass values to a template. As I never did this with strings, it might not work.
template<auto T>
struct DebugHelper : IDebug
{
static std::string format() { return T; }
std::string format_impl() const override { return T; }
};
struct MooDebug : DebugHelper< "whatever">
{};
based on #JVApen answer I ended up doing this:
template <class T>
struct IDebug {
void print(std::ostream& o) const { // no longer virtual
auto myformat = T::format();
// preprocess using format
print_impl(o);
// postprocess using format
}
protected:
virtual void print_impl(std::ostream& o) const = 0;
};
now we also force (up to not using the CRTP correctly) the static implementation of format() which is a nice added bonus
I have a little problem with an exercise. I have 2 classes :
The first :
namespace Abstract{
class AbstractClass{
public:
virtual void setName(const std::string & _name) =0;
virtual void print() =0;
void DynamicCastTest(){};
};
}
The second :
class ConcreteClass : public Abstract::AbstractClass{
std::string type;
public:
ConcreteClass();
ConcreteClass(const char* a);
~ConcreteClass();
static Abstract::AbstractClass* CreateConcreteClass(const char* a);
virtual void setName(const std::string & _name);
virtual void print();
};
And the cpp file of the second class :
#include "concreteClass.h"
ConcreteClass::ConcreteClass(){
type = "";
}
ConcreteClass::ConcreteClass(const char* a){
type = a;
}
ConcreteClass::~ConcreteClass(){}
static ConcreteClass* CreateConcreteClass(const char* a){
return new ConcreteClass(a);
}
void ConcreteClass::setName(const std::string & _name){
type = _name;
}
void ConcreteClass::print(){
std::cout<<type<<std::endl;
}
But in my main, when i call :
const char* s = "";
Abstract::AbstractClass* a = ConcreteClass::CreateConcreteClass(s);
In the compilation, Visual out me an error LNK2019 :
"public: static class ConcreteClass * __cdecl ConcreteClass::CreateConcreteClass(char const *)" (?CreateConcreteClass#ConcreteClass##SAPAV1#PBD#Z)
on this last line. Why ?
Ah, got it:
static ConcreteClass* CreateConcreteClass(const char* a){
return new ConcreteClass(a);
}
is not a declaration of:
ConcreteClass::CreateConcreteClass(s)
I'll leave it to you to figure out what the fix is, as it's a good learning experience, and I'm 100% sure you don't need to practice copy'n'paste - or you could just wait, because I'm sure someone else will post a "fixed" answer soon, simply because they don't care if you learn or not.
Edit: to clarify. You have declared a static member function in the class. And you have defined a static function that is not a member of any class.
You declare CreateConcreateClass as:
static Abstract::AbstractClass* CreateConcreteClass(const char* a);
but then later on we have this, which is a static function but not the one you declared in your class:
static ConcreteClass* CreateConcreteClass(const char* a){
return new ConcreteClass(a);
}
the signature has to match your declaration, and so it should be this:
Abstract::AbstractClass* ConcreteClass::CreateConcreteClass(const char* a){
return new ConcreteClass(a);
}
I have an existing project with the following class inheritance
class Base
{
public:
Base();
virtual ~Base();
void SetID(unsigned short);
virtual inline unsigned short GetID();
protected:
unsigned short id;
};
class Generic : public Base {
public:
Generic(const char *in_name);
const char* GetName() { return name; }
protected:
char name[30];
};
class Actor : public Generic
{
public:
Actor(const char *in_name);
~Actor();
void DoSomething(const char* str);
};
Now i created a separate project were i want to provide an interface that has to be implemented in order to use the functionality - i plan on reusing this project for other implementation.
class MyInterface
{
public:
virtual ~MyInterface() {}
// Our methods that need to implemented
virtual const char* GetName() = 0;
virtual void DoSomething(const char* str) = 0;
virtual unsigned short GetID() = 0;
};
Now i simply wanted to use this with my actor class e.g.
class Actor : public Generic, public MyInterface
however it fails to compile
'const char *MyInterface::GetName(void)' : is abstract see declaration of 'MyInterface::GetName'
'unsigned short MyInterface::GetID(void)' : is abstract see declaration of 'MyInterface::GetID'
error C2385: ambiguous access of 'GetName'
could be the 'GetName' in base 'Generic'
or could be the 'GetName' in base 'MyInterface'
The problem is probably that GetName is already implemented in Generic, and GetID is already implemented in Base - so in the child class Actor implementing the Interface is not possible because the compiler is not smart enough to realize there is already an implementation of these methods.
However, i found a workaround - but for this i would have to extend the header of the actor class which is not a nice thing - and i wanted to know if there is another approach - my fix is
class Actor : public Generic, public MyInterface
{
public:
Actor(const char *in_name);
~Actor();
void DoSomething(const char* str);
const char* GetName() { return Generic::GetName(); };
inline unsigned short GetID() { return Base::GetID(); };
};
Now this obviously will not work for varargs methods and i would have to implement existing methods and delegate to the parent again - is there a better solution?
EDIT For clarifications - the classes base,generic and actor exist in another project managed by others, modifications to these should be very limited. - I created a seperate project which creates a static LIB - to use functions of these in conjunction with the actor class - i created an interface to not have any dependency in my own project and also provide a reusable lib for other projects which would simply just need to implement this interface.
class Base
{
protected:
unsigned short id;
public:
void SetID(unsigned short);
virtual inline unsigned short GetID() { return id; }
virtual ~Base() {}
Base(): id() {}
};
class Generic
: public Base
{
protected:
char name[30];
public:
const char* GetName() { return name; }
Generic(const char* in_name): name() {}
};
class Actor
: public Generic
{
public:
void DoSomething(const char* str) {}
~Actor() {}
Actor(const char* in_name)
: Generic( name )
{}
};
class MyInterface
{
public:
// Our methods that need to implemented
virtual const char* name() const = 0;
virtual int id() const = 0;
virtual void doSomething( const char* str ) = 0;
virtual ~MyInterface() {}
};
template< class TpBase >
class MyInterfaceOn
: public virtual MyInterface
, public TpBase
{
public:
typedef TpBase Base;
private:
MyInterfaceOn& mutableSelf() const
{ return *const_cast<MyInterfaceOn*>( this ); }
public:
const char* name() const { return mutableSelf().Base::GetName(); }
int id() const { return mutableSelf().Base::GetID(); }
void doSomething(const char* str) { Base::DoSomething( str ); }
MyInterfaceOn( char const name[] )
: Base( name )
{}
};
class MyActor
: public MyInterfaceOn< Actor >
{
public:
MyActor( char const name[] )
: MyInterfaceOn< Actor >( name )
{}
};
int main()
{
MyInterface const& actor = MyActor( "NN" );
}