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
Related
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.
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 am trying to create abstract class which is a template for another classes. Is it possible to create "flexible" template?
Several classes will inherit from this one, all of them will have the functions with the same name, but with different arguments. The abstract class is "Interface" of inheritance classes - I will use pointer of this one to manage another.
For example we have two classes: A and B.
find method of A class needs only type1 type, but the same method of B class needs type1 and type2 types.
This is how I am creating classes that inherit from template:
class A : public Repository<int> {
public void find(int) override; };
class B : public Repository<int, float> {
public void find(int a, float b) override; };
Its all about the part after public keyword. I don't want to type <int, float> to all classes.
I there any way to overload(?) the template<typename type1, typename type2> and the function?
The code of the abstract class.
#ifndef REPOSITORY_HPP
#define REPOSITORY_HPP
#include <string>
//template<typename type1>
template<typename type1, typename type2>
class Repository
{
protected:
typeSTRING name;
public:
virtual void find(type1) = 0;
//virtual void find(type1, type2) = 0;
};
#endif
You would need variadic template in base class, i.e
#include <iostream>
template <typename ... Args>
class Interface
{
public:
virtual void find(Args... args) = 0;
};
class Impl1 : public Interface<int>
{
public:
void find(int value) override
{
std::cout << "found" << value << std::endl;
}
};
class Impl2 : public Interface<int, float>
{
public:
void find(int value, float other_value) override
{
std::cout << "found" << value << " " << other_value << std::endl;
}
};
int main()
{
Impl1 impl1 {};
impl1.find(5);
Impl2 impl2 {};
impl2.find(5, 10.2);
}
To complement the below comment from #KKMKK, this is how you can get an specific type from Args... (from: get the Nth type of variadic template templates?):
template <typename ... Args>
class Interface
{
public:
using FirstType = typename std::tuple_element<0, std::tuple<Args...> >::type;
virtual void add(FirstType) = 0;
virtual void find(Args... args) = 0;
};
class Impl2 : public Interface<int, float>
{
public:
void add(int value) override
{
std::cout << "found" << value << std::endl;
}
void find(int value, float other_value) override
{
std::cout << "found" << value << " " << other_value << std::endl;
}
};
int main()
{
Impl2 impl2 {};
impl2.add(5);
impl2.find(5, 10.2);
}
Suppose I have a base class as below:
template <typename T>
class Base {
// implementation
void do_something() { /* ... */ } ;
};
then, I create a Derived class as below, and override the do_something() method:
template <typename T>
class Derived : public Base<T> {
// implementation
void do_something() { /* ... */ } ;
};
I know virtualization does not work in class templates, and I am just hiding the implementation of the methods. but I do want to store a bunch of derived classes and base classes into a vector, (I do not want to use type erasure, or polymorphism),
my question is, given that static_cast of Derived class to base class gives me the do_something of based class, Is there any way that I can store them as base classes while each has their implementation of do_something() class ?
but I do want to store a bunch of derived classes and base classes into a vector, (I do not want to use type erasure, or polymorphism),
This is already just not possible in C++. In C++, a vector can only contain objects of the same static type. The only way a vector can contain different types of objects is if their static type is still the same, but they have different dynamic types, but this is type erasure/polymorphism which you said you don't want to use.
I think maybe you need to rethink your requirements, because your question in essence reads: I want to do something, but I don't want to use technique X which is explicitly defined as the only way to do that something in C++!
I did this and it seems to work fine:
#include <iostream>
template <typename T>
struct Base {
virtual void do_something() { std::cout << "Base::do_something()\n"; }
};
template <typename T>
struct Derived : public Base<T> {
virtual void do_something() { std::cout << "Derived::do_something()\n"; }
};
int main() {
Base<int> b;
Derived<int> d;
Base<int> *p;
p = &b;
p->do_something();
p = &d;
p->do_something();
return 0;
}
Output:
Base::do_something()
Derived::do_something()
A little variation of the melpomene's answer (adding a no-template base struct, BaseOfBase, for the Base<T> structs) permit the use of a common vector of base of derived classe of different T types.
A working example
#include <vector>
#include <iostream>
struct BaseOfBase
{ virtual void do_something () = 0; };
template <typename T>
struct Base : public BaseOfBase
{
T val;
void do_something ()
{ std::cout << "Base::do_something() [" << val << "]\n"; };
};
template <typename T>
struct Derived : public Base<T>
{ void do_something()
{ std::cout << "Derived::do_something() [" << this->val << "]\n"; } };
int main ()
{
std::vector<BaseOfBase*> vpbb;
Base<int> bi;
Derived<int> di;
Base<std::string> bs;
Derived<std::string> ds;
bi.val = 1;
di.val = 2;
bs.val = "foo";
ds.val = "bar";
vpbb.push_back(&bi);
vpbb.push_back(&di);
vpbb.push_back(&bs);
vpbb.push_back(&ds);
for ( auto const & pbb : vpbb )
pbb->do_something();
}
When we say virtualization doesn't work in template classes, we don't mean that you can't do virtual functions in a template class, nor does it mean that you cannot override a member function with a specialized version of it.
#melpomene showed an example of overriding in general, and I will show here with specialization:
#include <iostream>
template <typename T>
class Base {
public:
virtual T do_something(T in) { std::cout << "Base::do_something()\n"; return in; }
};
class Derived : public Base<int> {
public:
virtual int do_something(int in) { std::cout << "Derived::do_something()\n"; return in - 1; }
};
void main()
{
Base<int> b;
Derived d;
Base<int> *p = &b;
auto r1 = p->do_something(10);
std::cout << r1 <<std::endl;
p = &d;
auto r2 = p->do_something(10);
std::cout << r2 << std::endl;
}
Which will output
Base::do_something()
10
Derived::do_something()
9
Showing that it perfectly works as expected.
What we do mean when saying that
virtualization does not work in class templates
Basically means that you can't use as a template the derived class when the base is expected.
Consider the above classes Base<T> and Derived, then if we have the following code:
#include <memory>
template <typename T>
void Test(std::unique_ptr<Base<T>> in){ std::cout << "This will not work with derived"; }
void main()
{
Base<int> b;
Derived d;
auto ptr = std::unique_ptr<Derived>(&d);
Test(ptr); // <-- Will fail to compile as an invalid argument
}
it will fail because std::unique_ptr<Derived> does not inherit from std::unique_ptr<Base<T>> although Derived itself inherits from Base<T>.
I faced a problem that could be solved with the visitor pattern, and because I love reusable code I thought it might be a good idea to have some classes that already do most of the magic for me and which I could reuse later. So what I wanted was something like a Visitor class and a Visitable class, from which I can derive to prepare my deriving class for the use of the visitor pattern. I came up with this code:
template <typename ret = void>
class Visitor
{
public:
typedef ret ReturnType;
protected:
Visitor() {}
~Visitor() {}
};
template <typename BaseType>
class Visitable
{
public:
template <typename Visitor>
typename Visitor::ReturnType applyVisitor(Visitor& visitor)
{
return visitor(static_cast<BaseType*>(this));
}
template <typename Visitor>
typename Visitor::ReturnType applyVisitor(Visitor& visitor) const
{
return visitor(static_cast<BaseType*>(this));
}
protected:
Visitable() {}
~Visitable() {}
};
template <typename VisitorType, typename VisitableType>
inline typename VisitorType::ReturnType applyVisitor(VisitorType visitor, VisitableType visitable)
{
return visitable->applyVisitor(visitor);
}
class Base : public Visitable <Base>
{
public:
virtual void foo() const
{
std::cout << "BASE" << std::endl;
};
std::string foobar() const
{
return "BASE";
};
};
class Derived : public Base, public Visitable<Derived>
{
public:
using Visitable<Derived>::applyVisitor;
void foo() const
{
std::cout << "DERIVED" << std::endl;
};
std::string bar() const
{
return "DERIVED";
};
};
struct MyVisitor : public Visitor < >
{
template <class T>
void operator()(T const var) const
{
var->foo();
}
};
struct MyOtherVisitor : public Visitor <std::string>
{
std::string operator()(Base * const var) const
{
return var->foobar();
}
std::string operator()(Derived * const var) const
{
return var->bar();
}
};
int main(int _Argc, char* _Argv)
{
Base *pVirtualDerived = new Derived();
Base *pBase = new Base();
Derived *pDerived = new Derived();
std::cout << "Member method:" << std::endl;
applyVisitor(MyVisitor(), pVirtualDerived);
applyVisitor(MyVisitor(), pBase);
applyVisitor(MyVisitor(), pDerived);
std::cout << std::endl << "External method:" << std::endl;
std::cout << applyVisitor(MyOtherVisitor(), pVirtualDerived) << std::endl;
std::cout << applyVisitor(MyOtherVisitor(), pBase) << std::endl;
std::cout << applyVisitor(MyOtherVisitor(), pDerived) << std::endl;
}
As one might already guess from the names I was inspired by boost::static_visitor and boost::variant. However, one can also notice that my implementation is flawed in two aspects:
It does not suffice to just inherit from Visitable, I also need to put a using declaration into my class to resolve ambiguity for the applyVisitor method.
It is not really the visitor pattern. Calling applyVisitor with a Base* that actually points to a Derived object does not call Derived::foo but Base::foo. I cannot declare applyVisitor in Visitable<T> virtual because it is a templated method. But I need the template because Visitor<T> is a template class it self and I would like to keep the generic return type for my visitors.
Long story short, can I somehow solve both problems and end up with two classes from which I simply need to derive to prepare my code for the visitor pattern?
There are lots of things to talk about Visitor Design Patterns and C++ inheritance. In the specific case that you described, I think the solutions are:
About the first problem, since the Base class is already inheriting from Visitable, you don't need to inherit from it again in the derived class:
class Derived : public Base
{
public:
void foo() const
{
std::cout << "DERIVED" << std::endl;
};
};
About the second problem, I think you just forgot the virtual keyword in the Base class:
class Base : public Visitable<Base>
{
public:
virtual void foo() const
{
std::cout << "BASE" << std::endl;
};
};