Is there a way to statically (i.e. at compile time) get the base class of a given class?
That is, given:
class Base {};
class Derived1: public Base {};
class Derived2: public Derived1 {};
class Derived3: public Derived2 {};
For example is_base_of<Base,Derived3> gives true.
I'd like to know if there is something like base_of<Derived3> that would give Base.
In case, there is a solution (which I doubt), I'd also like to know if there is a possibility to get the direct child of Base. For example something like base_child_of<Derived3> would give Derived1.
ADDENDUM
Here is a not so beautiful solution but it does the job. Especially, I do not like to have to write two time the class parent name (for example: class Derived2 : public Derived1 { HIERARCHY(Derived1) }; but I didn't find any solution that doesn't impair the curly brackets in most IDE editors, by adding one in the define):
#include <iostream>
#include <type_traits>
#define HIERARCHY(PARENT) public: using inherited = PARENT; using base = inherited::base;
class Base { public: using base = Base; };
class Derived1 : public Base { HIERARCHY(Base ) };
class Derived2 : public Derived1 { HIERARCHY(Derived1) };
class Derived3 : public Derived2 { HIERARCHY(Derived2) };
// Expands to:
// class Base { public: using base = Base; };
// class Derived1 : public Base { public: using inherited = Base; using base = inherited::base; };
// class Derived2 : public Derived1 { public: using inherited = Derived1; using base = inherited::base; };
// class Derived3 : public Derived2 { public: using inherited = Derived2; using base = inherited::base; };
// Not really needed anymore, now CLASS::base does the stuff
// (I leave it here to illustrate how a static loop/recursion may be performed)
template <typename CLASS>
struct base_of {
using type = typename std::conditional<
std::is_same<CLASS, Base>::value,
CLASS,
typename std::conditional<
std::is_base_of<typename CLASS::base, CLASS>::value,
typename base_of<typename CLASS::inherited>::type,
CLASS
>::type
>::type;
};
template<>
struct base_of<Base> {
using type = Base;
};
template <typename CLASS>
struct direct_child_of_base_of {
using type = typename std::conditional<
std::is_same<typename CLASS::inherited, typename CLASS::base>::value,
CLASS,
typename direct_child_of_base_of<typename CLASS::inherited>::type
>::type;
};
template<>
struct direct_child_of_base_of<Base> {
using type = void;
};
int main() {
std::cout << "dbase_of<Derived3>: " << typeid(base_of<Derived3>::type).name() << std::endl;
std::cout << "dbase_of<Derived2>: " << typeid(base_of<Derived2>::type).name() << std::endl;
std::cout << "dbase_of<Derived1>: " << typeid(base_of<Derived1>::type).name() << std::endl;
std::cout << "dbase_of<Base >: " << typeid(base_of<Base >::type).name() << std::endl;
std::cout << std::endl;
// This is equivalent
std::cout << "Derived3::base: " << typeid(Derived3::base).name() << std::endl;
std::cout << "Derived2::base: " << typeid(Derived2::base).name() << std::endl;
std::cout << "Derived1::base: " << typeid(Derived1::base).name() << std::endl;
std::cout << "Base ::base: " << typeid(Base ::base).name() << std::endl;
std::cout << std::endl;
std::cout << "direct_child_of_base_of<Derived3>: " << typeid(direct_child_of_base_of<Derived3>::type).name() << std::endl;
std::cout << "direct_child_of_base_of<Derived2>: " << typeid(direct_child_of_base_of<Derived2>::type).name() << std::endl;
std::cout << "direct_child_of_base_of<Derived1>: " << typeid(direct_child_of_base_of<Derived1>::type).name() << std::endl;
std::cout << "direct_child_of_base_of<Base >: " << typeid(direct_child_of_base_of<Base >::type).name() << std::endl;
return 0;
}
The output is (with GCC):
base_of<Derived3>: 4Base
base_of<Derived2>: 4Base
base_of<Derived1>: 4Base
base_of<Base >: 4Base
Derived3::base: 4Base
Derived2::base: 4Base
Derived1::base: 4Base
Base ::base: 4Base
direct_child_of_base_of<Derived3>: 8Derived1
direct_child_of_base_of<Derived2>: 8Derived1
direct_child_of_base_of<Derived1>: 8Derived1
direct_child_of_base_of<Base >: v
This is possible, with some limitations, by using stateful metaprogramming to record the type deduced for a universal conversion operator used to construct the subobjects of the derived type in aggregate initialization (assuming it is an aggregate). For example, we can write:
template<class T>
struct first_direct_base {
template<class U>
struct Y {
friend auto f(first_direct_base*) { return U(); }
};
friend auto f(first_direct_base*);
struct A {
template<class U, int = sizeof(Y<U>)>
operator U();
};
using type = decltype(T{A{}}, f((first_direct_base*)0));
};
template<class T>
using first_direct_base_t = first_direct_base<T>::type;
Demo.
For a fuller explanation of this technique, see http://alexpolt.github.io/type-loophole.html
If you're happy with using manual reflection, I'd recommend Boost.Describe. For example, with the above you might write:
class Base { BOOST_DESCRIBE_CLASS(Base, (), (), (), ()) };
class Derived1: public Base { BOOST_DESCRIBE_CLASS(Derived1, (Base), (), (), ()) };
template<class T>
using first_direct_base_t = boost::mp11::mp_front<
boost::describe::describe_bases<T, boost::describe::mod_public>>;
Currently no, not in standard C++.
There are reflection proposals that are being worked on. The original plan was to have them published in c++23, but between an improved syntax proposal and the Covid-19 pandemic, it was postponed.
When reflection arrives, this will be possible. The syntax was still in flux last I checked. Either c++26 or c++29.
Related
I'm currently coding a program in c++ using a template class:
template<typename TYPE>
class TemplateClass {
private:
TYPE t;
};
I have another class which acts as manager of my TemplateClass which should store multiple instances of this class in a vector. Different instances should have different types e.g. int, std::string, etc.. Speaking in Java ways the solution would be to just use something like in the example below but it seems like this is not possible in C++.
class ManagerClass {
private:
// Here seems to be the problem.
std::vector<TemplateClass<?>> templates;
}
Is it possible to do something like that?
Thank you for all answers
If you know all the types that will be stored in the std::vector at compile time I'd use an std::variant in such a case.
// This is used for the visitor pattern.
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
// The below line not needed in C++20...
template<class... Ts> overload(Ts...) -> overload<Ts...>;
template<typename T>
struct MyClass { T value; };
using types = std::variant<
MyClass<std::string>,
MyClass<int>,
MyClass<double>>;
int main()
{
std::vector<types> stuff{};
stuff.push_back(MyClass<std::string>{});
stuff.push_back(MyClass<int>{});
stuff.push_back(MyClass<double>{});
for(const auto& v : stuff)
{
if (std::holds_alternative<MyClass<std::string>>(v))
{
std::cout << "Im a string\n";
}
else if (auto* p{std::get_if<MyClass<int>>(&v)})
{
std::cout << "Im an int\n";
}
else
{
auto t = std::get<MyClass<double>>(v);
std::cout << "Im a double\n";
}
// Or you can use the visitor pattern.
std::visit(overload{
[](const MyClass<std::string>& ) { std::cout << "I'm a string\n"; },
[](const MyClass<int>& ) { std::cout << "I'm a int\n"; },
[](const MyClass<double>& ) { std::cout << "I'm a double\n"; },
}, v);
}
}
If you can use C++17, you can use std::any or std::variant.
class ManagerClass {
private:
using variant_type = std::variant<
TemplateClass<std::string>,
TemplateClass<int>,
TemplateClass<double> >;
std::vector<variant_type> templates;
};
This is one way of doing it via runtime polymorphishm, which is achieved by function overriding. Function overriding occurs when a derived class has a definition for one of the member functions of the base class. That base function is said to be overridden.
#include <iostream>
#include <vector>
using namespace std;
// Base class declaration
class Base {
public:
virtual void print()
{
cout << "Base" << endl;
}
virtual ~Base(){}
};
// Derived Class 1
class Derived1 : public Base {
public:
void print()
{
cout << "Derived1" << endl;
}
};
// Derived class 2
class Derived2 : public Base {
public:
void print()
{
cout << "Derived2" << endl;
}
};
int main()
{
Base* d1 = new Derived1();
Base* d2 = new Derived2();
vector<Base*> myVec;
myVec.push_back(d1);
myVec.push_back(d2);
for (auto i : myVec) {
i->print();
}
delete d1;
delete d2;
return 0;
}
I'm on a personal project and I need to do something unusual. My code is kinda long but the problem comes from the structure so I'll use a very simplified version of the problem.
I have two classes (A and B), with B derived from A.
B uses every attributes and methods of A, including one which creates a modified
clone of the instance of the class.
The problem is that I need to be able to use a method of B after cloning (moo in this case) that doesn't exists in A. I tried to make my methods virtual but it doesn't fix the problem. Is there any way to do this without CRTP ?
I really don't want to use CRTP because it would be really complicated.
(In my real code I have a chain of 4 class inheritances, and all 4 are already templated)
#include <iostream>
class A
{
public:
/*Common function*/
virtual void foo(){
std::cout << "call from A" << std::endl;
}
A* clone(){
/*
...
... Code I don't want to write again for B
...
*/
return this;
}
};
class B: public A
{
public:
/*Common function*/
virtual void foo(){
std::cout << "call from B" << std::endl;
}
/*Not derived from A*/
void moo(){ //Doesn't work even with virtual keyword
std::cout << "only exist in B" << std::endl;
}
};
int main(int argc, char const *argv[])
{
auto tB = new B();
tB->foo();
tB->moo();
tB->clone()->foo();
tB->clone()->moo();
return 0;
}
Compilator:
error: 'class A' has no member named 'moo'; did you mean 'foo'?
38 | tB->clone()->moo();
| ^~~
| foo
I'm not English so sorry if it's unclear.
Well, according to the comments, my research and how I think c++ works, I give up finding something that looks like virtual methods and still be satisfying.
So I resolved to use the CRTP, for those who are interested here's the code of my model of a 3 (I deleted one) inherited class CRTP with an additional type template argument :)
#include <iostream>
//CRTPI = "CRTP Interface", used for inheritances between CRTPs
template<typename Derived, typename T>
class CRTPI_A
{
protected:
T x = 0;
public:
T getX(){
return x;
}
Derived* clone(){
/*
...
... Code I don't want to write again for B and it's childs
...
*/
return new Derived();
}
};
template<typename Derived, typename T>
class CRTPI_B: public CRTPI_A<Derived, T>
{
public:
//Only for B and its childs
void iwd(){
std::cout << "Hi, i'm a B child !" << std::endl;
}
};
template<typename Derived, typename T>
class CRTPI_C: public CRTPI_B<Derived, T>{};
template<typename T>
class A: public CRTPI_A<A<T>, T>
{
public:
A(){};
A(T z){
this->x = z;
}
void foo(){
std::cout << "call from A" << std::endl;
}
};
template<typename T>
class B: public CRTPI_B<B<T>, T>
{
public:
B(){};
B(T z){
this->x = z;
}
void foo(){
std::cout << "call from B" << std::endl;
}
//Not in CRTP interface so won't be inherited by C
void UwU(){
std::cout << "I'm exclusive to B" << std::endl;
}
};
template<typename T>
class C: public CRTPI_C<C<T>, T>
{
public:
C(){};
C(T z){
this->x = z;
};
void foo(){
std::cout << "call from C" << std::endl;
}
};
int main(int argc, char const *argv[])
{
auto tA = new A<char>('A');
auto tB = new B<int>(2);
auto tC = new C<float>(420.69);
tA->foo();
tA->clone()->foo();
printf("\n");
tB->foo();
tB->iwd();
tB->clone()->foo();
tB->clone()->iwd();
tB->UwU();
printf("\n");
tC->foo();
tC->iwd();
// tC->UwU(); //Won't work but that's planned
std::cout << "\n" << tA->getX() << ":" << tB->getX() <<":" << tC->getX() << std::endl;
return 0;
}
Note that, here, the CRTP interface for C is optional because it has no child class and no exclusive methods, so we can just write:
template<typename T>
class C: CRTPI_B<C<T>, T>
{
...
}
I want to write a C++ mechanism, where different instantiations of a function are called if a given class Param is derived from a certain base class.
This works pretty nicely with std::is_base_of and std::enable_if.
However, I would like to have a "default version" of this doStuff() function that is called for "every other class".
This would basically work by doing something like "if Param is not derived from A and if not derived from B", but I wonder whether there is a more elegant solution.
#include <iostream>
class A {};
class B : public A {};
class X {};
class Y : public X {};
class Other {};
template <typename Param, std::enable_if_t<std::is_base_of<A, Param>::value, bool> = true>
void doStuff() {std::cout << "Base A" << std::endl;};
template <typename Param, std::enable_if_t<std::is_base_of<X, Param>::value, bool> = true>
void doStuff() {std::cout << "Base X" << std::endl;};
int main()
{
doStuff<B>();
doStuff<Y>();
// doStuff<Other>(); this is neither derived from B and Y, so call the default case
}
The solution should work with C++14.
When using std:::enable_if, you will have to provide a 3rd SFINAE'd overload that handles the default conditions which are not handled by the other overloads, eg:
#include <iostream>
#include <type_traits>
class A {};
class B : public A {};
class X {};
class Y : public X {};
class Other {};
template <typename Param, std::enable_if_t<std::is_base_of<A, Param>::value, bool> = true>
void doStuff() { std::cout << "Base A" << std::endl; }
template <typename Param, std::enable_if_t<std::is_base_of<X, Param>::value, bool> = true>
void doStuff() { std::cout << "Base X" << std::endl; }
template <typename Param, std::enable_if_t<!(std::is_base_of<A, Param>::value || std::is_base_of<X, Param>::value), bool> = true>
void doStuff() { std::cout << "Something else" << std::endl; }
int main()
{
doStuff<B>(); // prints "Base A"
doStuff<Y>(); // prints "Base X"
doStuff<Other>(); // prints "Something else"
}
Online Demo
That being said, in C++17 and later, you can use if constexpr instead, which is cleaner than using SFINAE in this situation, eg:
#include <iostream>
#include <type_traits>
class A {};
class B : public A {};
class X {};
class Y : public X {};
class Other {};
template <typename Param>
void doStuff() {
if constexpr (std::is_base_of_v<A, Param>)
std::cout << "Base A" << std::endl;
else if constexpr (std::is_base_of_v<X, Param>)
std::cout << "Base X" << std::endl;
else
std::cout << "Something else" << std::endl;
}
int main()
{
doStuff<B>(); // prints "Base A"
doStuff<Y>(); // prints "Base X"
doStuff<Other>(); // prints "Something else"
}
Online Demo
Or if you can use C++17 or later use constexpr, a lot more readable then SFINAE
#include <type_traits>
#include <iostream>
class A {};
class B : public A {};
class X {};
class Y : public X {};
class Other {};
template<typename type_t>
void doStuff()
{
if constexpr (std::is_base_of_v<A,type_t>)
{
std::cout << "Base A\n";
}
else
if constexpr (std::is_base_of_v<X, type_t>)
{
std::cout << "Base X\n";
}
else
{
std::cout << "Other\n";
}
};
int main()
{
doStuff<B>();
doStuff<Y>();
doStuff<Other>(); //this is neither derived from B and Y, so call the default case
return 0;
}
I have a base class
template<typename T>
class Base {};
and a few derived classes:
class DerivedInt : public Base<int> {}
class DerivedDummy : public Base<Dummy> {}
// where Dummy is some user-defined concrete type
template<typename E>
class DerivedGeneric : public Base<E> {}
I wish to write a type trait function f<DerivedType>::value that returns true only when there exists a type T such that DerivedType inherits from Base<T>.
I feel that SFINAE is the way to go ... but I'm not too familiar with the metaprogramming black magic. Thanks!
I believe the type support templates in C++11 are what you want, especially std::is_base_of.
I am not sure, if std::is_base_of could be helpful in this case, but you could surely use std::is_convertible.
If there exists type T, such that Derived inherits from Base<T>, it means, that Derived is implicitly-convertible to Base<T>.
So, you can simply use following solution. It is compile-time detection in such way, that it won't compile if you call checking function for type, that does not fulfil your requirements. Check this code:
#include <iostream>
struct Dummy
{
};
template<typename T>
class Base
{
};
class DerivedInt : public Base<int>
{
};
class DerivedDummy : public Base<Dummy>
{
};
template<typename E>
class DerivedGeneric : public Base<E>
{
};
template <class T>
bool is_derived_from_base_t_impl(Base<T>* impl)
{
return true;
}
template <class Derived>
bool is_derived_from_base_t()
{
Derived* d = nullptr;
return is_derived_from_base_t_impl(d);
}
int main()
{
std::cout<< is_derived_from_base_t< DerivedInt >() <<"\n";
std::cout<< is_derived_from_base_t< DerivedDummy >() <<"\n";
std::cout<< is_derived_from_base_t< DerivedGeneric<float> >() <<"\n";
return 0;
}
Output:
1
1
1
However, if you do:
is_derived_from_base_t< float >();
You will get:
error C2784: 'bool is_derived_from_base_t_impl(Base<T> *)' : could not deduce template argument for 'Base<T> *' from 'float *'
(Output from VC++ 11)
An improvement to Mateusz Grzejek's solution to make a real traits:
template <class T>
std::true_type is_derived_from_base_t_impl(const Base<T>* impl);
std::false_type is_derived_from_base_t_impl(...);
template <class Derived>
using is_derived_from_base_t =
decltype(is_derived_from_base_t_impl(std::declval<Derived*>()));
Live demo
Note that doesn't handle multiple inheritance.
Several more aspects answered
* independence from C++11 features
* private inheritance
* virtual inheritance
* multiple inheritance
* inheritance from struct
* symmetric relationship, i.e. forward or reverse inheritance
/**
* Class Template InheritanceCheck
* #param Candidate - type optionally inherited from Base
* #param Base - base class/struct
*/
template<typename Candidate, typename Base>
class InheritanceCheck
{
static char Test(Base*);
static int Test(...);
static void Constraints(Candidate* p) { }
InheritanceCheck()
{
void(*p)(Candidate*) = Constraints;
};
public:
/**
* isSub, true when Candidate is derived from Base
*/
static const bool isSub = sizeof(Test(static_cast<Candidate*>(0))) == sizeof(char);
/**
* isRelated, true when Candidate is derived from Base OR Base is derived from Candidate
*/
static const bool isRelated = isSub || InheritanceCheck<Base,Candidate>::isSub;
};
// Access policy for class InheritanceCheck in case of protected/private inheritance
#define ICP template<typename Candidate, typename Base> friend class InheritanceCheck
/* Example */
class A {};
class B : virtual A { ICP; };
class C : public virtual A, public B {};
struct D {};
struct S {};
class Z : public S {};
int main()
{
std::cout << "B->A " << InheritanceCheck<B, A>::isSub << std::endl;
std::cout << "C->A " << InheritanceCheck<C, A>::isSub << std::endl;
std::cout << "C->B " << InheritanceCheck<C, B>::isSub << std::endl;
std::cout << "D->A " << InheritanceCheck<D, A>::isSub << std::endl;
std::cout << "A->B " << InheritanceCheck<A, B>::isSub << std::endl;
std::cout << "A~B " << InheritanceCheck<A, B>::isRelated << std::endl;
std::cout << "S->A " << InheritanceCheck<S, A>::isSub << std::endl;
std::cout << "Z->S " << InheritanceCheck<Z, S>::isSub << std::endl;
}
Output:
B->A 1
C->A 1
C->B 1
D->A 0
A->B 0
A~B 1
S->A 0
Z->S 1
I have a series of classes that tells the debug stream (std::cout in this case) that it has been created, allowing me to follow the program execution nicely. I have several classes that are subclasses of base classes which are not abstract, which results in a double message when a subclass instance is created. I would like to suppress the output in the base class constructor when it is called from a subclass. I know this probably isn't possible without some fancy trick, if it is even possible at all.
I did think of using the backspace escape sequence \b, and doing just enough of that to delete the previous message not really efficient, but it's debug info, performance isn't that critical then...). I'm not sure of the portability or effectiveness of this approach.
Any ideas are welcome, thanks for the effort!
There's no way to suppress the code in the base constructor, unless the code in the base constructor checks some condition itself. You may achieve this by e.g. passing a special flag to the base constructor (having default value NOT prohibiting the debug output).
class Base
{
public:
Base(bool suppressDebugInfo = false)
{
if (!suppressDebugInfo)
cout << "hallo from base" << endl;
}
};
class Derived : public Base
{
public:
Derived(bool suppressDebugInfo = false) : Base(true)
{
if (!suppressDebugInfo)
cout << "hallo from derived" << endl;
}
};
Outputting \b's won't help if your output is redirected to a file etc.
A decent solution could be to create a virtual function which returns a string, and output the result of that function. This won't however work for your case (calling from constructor), as during the base constructor run the virtual functions behave as if the instance is of the base type, not derived.
This implementation addresses some of Vlad's concerns. The main difference lies in the constructor signature, which is not affected by logging logic, although classes are templates now, which could be frightening, but as you all know, there's no free lunch out there. :) So, here we go:
#include <iostream>
template< bool IsLeafClass = true >
class AbstractBase
{
public:
AbstractBase() {
if ( IsLeafClass )
std::cout << "AbstractBase" << std::endl;
}
};
template< bool IsLeafClass = true >
class Base : AbstractBase< false > {
public:
Base() {
if ( IsLeafClass )
std::cout << "Base" << std::endl;
}
};
typedef Base<> CBase;
template< bool IsLeafClass = true >
class Derived : public Base< false > {
private:
CBase _base;
public:
Derived() {
if ( IsLeafClass )
std::cout << "Derived" << std::endl;
}
};
typedef Derived<> CDerived;
template < bool IsLeafClass = true >
class DerivedMore : public Derived< false > {
private:
CDerived _derived;
CBase _base;
public:
DerivedMore() {
if ( IsLeafClass )
std::cout << "DerivedMore" << std::endl;
}
};
typedef DerivedMore<> CDerivedMore;
int main()
{
std::cout << "logging for b" << std::endl;
CBase b;
std::cout << std::endl << "logging for d" << std::endl;
CDerived d;
std::cout << std::endl << "logging for dm" << std::endl;
CDerivedMore dm;
}
Actually, there is a way, but in this case, only thanks to the fact that the base classes are using the std::cout stream directly. One possible solution is to inherit std::streambuf class like this:
#include <iostream>
#include <streambuf>
class DummyStreambuf : public std::streambuf {};
This step is needed because std::streambuf constructor are protected. When you have DummyStreambuf (or whatever you name it), all you need to do is to change stream buffer on std::cout standard stream.
int main()
{
DummyStreambuf dummy;
std::cout << "test" << std::endl;
// save default stream buffer for later use
std::streambuf *buff = std::cout.rdbuf(&dummy);
// this line shouldn't print
std::cout << "test" << std::endl;
// restore default stream buffer
std::cout.rdbuf(buff);
std::cout << "test" << std::endl;
}
Of course, there is room for improvement here. You could write a simple singleton which could turn on and off std::cout output. Here is one possible implementation for single-threaded environment:
#include <iostream>
#include <streambuf>
class DummyStreambuf : public std::streambuf {};
class CoutSwitch
{
private:
DummyStreambuf _dummyBuf;
std::streambuf *_coutBuf;
CoutSwitch() : _coutBuf( std::cout.rdbuf() ) {}
static CoutSwitch &instance() {
static CoutSwitch _instance;
return _instance;
}
public:
static void turnOn() {
std::cout.rdbuf( instance()._coutBuf );
}
static void turnOff() {
std::cout.rdbuf( &instance()._dummyBuf );
}
};
int main()
{
std::cout << "test" << std::endl;
CoutSwitch::turnOff();
std::cout << "test" << std::endl;
CoutSwitch::turnOn();
std::cout << "test" << std::endl;
}