My problem is that I can't chain methods from Derived class when I already used Base class methods. I tried to mix topmost answers from Returning a reference to the derived class from a base class method and CRTP and multilevel inheritance, but the problem is one of them is always returning the same object, the other is returning void. I want Base class being able to be inherited by any other class.
[The naive solution to this problem is to make a() virtual and override it in class Derived. But what if Base is inherited by 100 other classes and have 100 other methods to override? This is not scaling good.]
[The other naive solution is to call methods from Derived class first, then from Base, but... just no]
So, is it possible to somehow compile the following snippet in native C++? (I am not interested in boost solutions). It would be ideal if main()'s code wouldn't change.
#include <iostream>
#include <type_traits>
template <typename T = void>
class Base
{
public:
T& a();
};
class Derived : public Base<Derived>
{
public:
Derived& b() {std::cout << "b\n"; return *this;}
};
int main()
{
Base base;
base
.a()
;
Derived derived;
derived
.a()
.b()
;
return 0;
}
template <typename T>
T& Base<T>::a()
{
std::cout << "a\n";
if(std::is_same<T, void>::value)
{
return *this;
}
else
{
return static_cast<T&>(*this);
}
}
If only i could write template <typename T = Base> class Base { ... :)
Not sure if it is what you want, but with C++17 and if constexpr, you might do:
template <typename T = void>
class Base
{
public:
auto& a()
{
std::cout << "a\n";
if constexpr (std::is_same_v<T, void>) {
return *this;
} else {
return static_cast<T&>(*this);
}
}
};
Demo
Before, you might use specialization.
Related
I have a class that inherits from a base class. The derived class has a template method. The base class has a specialized version of this method:
#include <iostream>
class Base {
public:
static void print(int i) { std::cout << "Base::print\n"; }
};
class Derived : public Base {
public:
static void print(bool b) { std::cout << "Derived::bool_print\n"; }
template <typename T>
static void print(T t) { std::cout << "Derived::print\n"; }
void Foo() {
print(1);
print(true);
print("foo");
}
};
int main()
{
Derived d;
d.Foo();
return 0;
}
The output is:
Derived::print
Derived::bool_print
Derived::print
The desired output is:
Base::print
Derived::bool_print
Derived::print
See code at https://onlinegdb.com/BY2znq8WV
Is there any way to tell Derived::Foo to use the specialization from Base instead of using the unspecialized version define in Derived?
Edit
The above example might be oversimplified as #Erdal Küçük showed. In actuality Derived subclasses from Base using CRTP, so it is not known if Base has a print method. A fuller example can be found at https://onlinegdb.com/N2IKgp0FY
This might help:
class Derived : public Base {
public:
using Base::print; //one of the many useful usages of the keyword 'using'
//...
};
See: Using-declaration in class definition
In our legacy project we have a function that takes reference to a base class and creates a copy of the derived class on the heap. This is solved essentially like this: https://godbolt.org/z/9ooM4x
#include <iostream>
class Base
{
public:
virtual Base* vclone() const = 0;
int a{7};
};
class Derived : public Base
{
public:
Derived()
{
a = 8;
}
Base* vclone() const override
{
return new Derived(*this);
}
};
Base* clone(const Base& original)
{
return original.vclone();
}
int main()
{
Derived d1;;
auto* d2 = clone(d1);
std::cout << d2->a << std::endl;
}
This works, but I would like to get rid of the boilerplate vclone method that we have to have in every single derived class.
We have hundreds of derived classes, some of them derived not directly from Base, but from some of the other derived classes too. So if we forget to override the vclone method, we may not even get a warning of the slicing that will happen.
Now, there is much to say about such a design, but this is 10-15 year old code that I try to modernize step by step. What I do look for, is a templatized version of clone that does not depend on a virtual method. What I want, is a clone function like this:
Base* clone(const Base& original)
{
return new <Actual Derived Type>(original);
}
The actual derived type is somewhat known, since a dynamic_cast will fail if trying to cast to it with wrong type, but I don't know if it is possible to access the actual type in a way that I want.
Any help would be appreciated.
I also think you probably cannot improve the code in the sense to make it shorter.
I would say this implementation is basically the way to go.
What you could do is to change the return value of Derived::clone to Derived *. Yes C++ allows this.
Then a direct use of Derived::clone yields the correct pointer type and Base::clone still works as expected
class Derived : public Base
{
public:
Derived()
{
a = 8;
}
Derived* vclone() const override // <<--- 'Derived' instead of 'Base'.
{
return new Derived(*this);
}
};
I would also rename to vclone member function to clone (There is no need to have two names).
The free function clone could be made a template so that it works for all classes and returns the right pointer type
template <class T>
T *clone(const T *cls)
{
return cls->clone();
}
However, all these changes do not make the code shorter, just more usable and perhaps more readable.
To make it a little shorter you might use an CRTP approach.
template <class Derived, class Base>
class CloneHelper: public Base {
Derived* vclone() const override
{
return new Derived(* static_cast<Derived *>(this) );
}
};
// then use
class Derived : public CloneHelper<Derived, Base>
{
public:
Derived()
{
a = 8;
}
};
However, I am not sure if it is worth it. One still must not forget the CloneHelper, it makes inheritance always public and you cannot delegate to the Base constructor so easily and it is less explicit.
You could use an outside clone function and typeid:
#include <typeindex>
#include <string>
#include <stdexcept>
#include <cassert>
template<class Derived_t, class Base_t>
Base_t *clone_helper(Base_t *b) {
return new Derived_t(*static_cast<Derived_t *>(b));
}
struct Base {
virtual ~Base() = default;
};
struct Derived : Base {};
Base *clone(Base *b) {
const auto &type = typeid(*b);
if (type == typeid(Base)) {
return clone_helper<Base>(b);
}
if (type == typeid(Derived)) {
return clone_helper<Derived>(b);
}
throw std::domain_error(std::string("No cloning provided for type ") + typeid(*b).name());
}
int main() {
Derived d;
Base *ptr = &d;
auto ptr2 = clone(ptr);
assert(typeid(*ptr2) == typeid(Derived));
}
This will find at runtime if you did not provide a clone method. It may be slower than usual. Sadly a switch is not possible since we cannot obtain the typeid of a type at compile time.
You may like to implement clone function in a separate class template, which is only applied to derived classes when an object of a derived class is created. The derived classes do not implement clone (keep it pure virtual) to avoid forgetting to override it in a further derived class.
Example:
struct Base {
virtual Base* clone() const = 0;
virtual ~Base() noexcept = default;
};
template<class Derived>
struct CloneImpl final : Derived {
using Derived::Derived;
CloneImpl* clone() const override { // Covariant return type.
return new CloneImpl(*this);
}
};
template<class T>
std::unique_ptr<T> clone(T const& t) { // unique_ptr to avoid leaks.
return std::unique_ptr<T>(t.clone());
}
struct Derived : Base {};
struct Derived2 : Derived {};
int main() {
CloneImpl<Derived> d1; // Apply CloneImpl to Derived when creating an object.
auto d2 = clone(d1);
auto d3 = clone(*d2);
CloneImpl<Derived2> c1; // Apply CloneImpl to Derived2 when creating an object.
auto c2 = clone(c1);
auto c3 = clone(*c2);
}
See https://stackoverflow.com/a/16648036/412080 for more details about implementing interface hierarchies without code duplication.
I have the following class:
class Base {
public:
Base() = default;
virtual ~Base() {};
}
And, let's say I have a unique_ptr to this class, aka:
using BasePtr = std::unique_ptr<Base>;
Now, let's assume I have a template class that inherits from the base class.
template <typename T>
class Derived : public Base {
public:
Derived() = default;
Derived(const T x) : some_variable(x) {};
~Derived() override {};
void hello() { std::cout << some_variable << std::endl; }
private:
T some_variable;
}
For arguments sake, let's say I have a factory method that creates a unique_ptr to some new instance, such as:
template <typename T>
auto make_class(const T& x) -> BasePtr {
return std::unique_ptr<Derived<T> >(new Derived<T>(x));
}
If I try to build this:
int main() {
auto ptr = make_class<int>(5);
if (ptr) {
ptr->hello();
}
return 0;
}
With C++11, this results in a compile error (saying that Base does not have a hello() method), because it seems that the actual instance stored in the unique_ptr is a Base, not a Derived.
Based on my understanding (at least if Derived wasn't templated), this should not be an issue. What's happening here?
You function make_class returns a BasePtr:
auto make_class(const T& x) -> BasePtr
Then in your main function you say:
auto ptr = make_class(5);
that is, ptr is a BasePtr. The function cannot know that the pointer actually points to a derived class. For this reason, there is no hello() function that could be invoked.
SOLVED!
I want to create an array of different typed objects using templates.
Therefore I have a non-template class (Base), and a derived template class from Base class.
What I want to know is how can i access to derived class' generic value (T val)?
class Base{
public:
// a function returns T val, it will be implemented in Derived class
// EDIT : virtual function here
};
template<class T>
class Derived: public Base {
public:
T val;
Derived(T x) {
val = x;
}
// implementation.. it returns val
// EDIT : Implementation of virtual function
};
Solution: dynamic_cast, Note that Base class should have at least one virtual function.
Base *p[2];
p[0] = new Derived<int>(24);
p[1] = new Derived<double>(82.56);
int a = dynamic_cast<Derived<int>*>(p[0])->val; // casts p[0] to Derived<int>*
double b = dynamic_cast<Derived<double>*>(p[1])->val; // casts p[1] to Derived<double>*
cout << a << endl;
cout << b << endl;
Last time i checked, You cannot acess derived class members from a base class(non virtual).
You could modify your code this way since you are using templates.The type and value are passed to base class at construction and you can then use it.
template<typename T>
class Base {
T ini;
public:
Base(T arg){ini = arg;}
T ret(){return ini;}
};
template<class T>
class Derived: public Base<T> {
public:
T val;
Derived(T x) : Base<T>(x) {
//Base(x);
val = x;
}
// implementation.. it returns val
};
You can then instantiate it as usual and use it.
Derived<int> e(5);
e.ret();
It look like you want CRTP
The idea is to access the derived class members inside the base class. Note that you won't be able to contain an heterogeneous list of them.
template<typename D>
struct Base {
void doThings() {
// access the derived class getT function
auto var = static_cast<D&>(*this).getT();
cout << var << endl;
}
};
template<typename T>
struct Derived : Base<Derived> {
T getT() {
return myT;
}
private:
T myT;
};
I am trying to use template meta-programming to determine the base class. Is there a way to get the base class automatically without explicitly specializing for each derived class?
class foo { public: char * Name() { return "foo"; }; };
class bar : public foo { public: char * Name() { return "bar"; }; };
template< typename T > struct ClassInfo { typedef T Base; };
template<> struct ClassInfo<bar> { typedef foo Base; };
int main()
{
ClassInfo<foo>::Base A;
ClassInfo<bar>::Base B;
std::cout << A.Name(); //foo
std::cout << B.Name(); //foo
}
for right now any automatic method would need to select the first declared base and would fail for private bases.
It's possible with C++11 and decltype. For that, we'll exploit that a pointer-to-member is not a pointer into the derived class when the member is inherited from a base class.
For example:
struct base{
void f(){}
};
struct derived : base{};
The type of &derived::f will be void (base::*)(), not void (derived::*)(). This was already true in C++03, but it was impossible to get the base class type without actually specifying it. With decltype, it's easy and only needs this little function:
// unimplemented to make sure it's only used
// in unevaluated contexts (sizeof, decltype, alignof)
template<class T, class U>
T base_of(U T::*);
Usage:
#include <iostream>
// unimplemented to make sure it's only used
// in unevaluated contexts (sizeof, decltype, alignof)
template<class T, class R>
T base_of(R T::*);
struct base{
void f(){}
void name(){ std::cout << "base::name()\n"; }
};
struct derived : base{
void name(){ std::cout << "derived::name()\n"; }
};
struct not_deducible : base{
void f(){}
void name(){ std::cout << "not_deducible::name()\n"; }
};
int main(){
decltype(base_of(&derived::f)) a;
decltype(base_of(&base::f)) b;
decltype(base_of(¬_deducible::f)) c;
a.name();
b.name();
c.name();
}
Output:
base::name()
base::name()
not_deducible::name()
As the last example shows, you need to use a member that is actually an inherited member of the base class you're interested in.
There are more flaws, however: The member must also be unambiguously identify a base class member:
struct base2{ void f(){} };
struct not_deducible2 : base, base2{};
int main(){
decltype(base_of(¬_deducible2::f)) x; // error: 'f' is ambiguous
}
That's the best you can get though, without compiler support.
My solutions are not really automatic, but the best I can think of.
Intrusive C++03 solution:
class B {};
class A : public B
{
public:
typedef B Base;
};
Non-intrusive C++03 solution:
class B {};
class A : public B {};
template<class T>
struct TypeInfo;
template<>
struct TypeInfo<A>
{
typedef B Base;
};
I am not aware of any base-class-selecting template, and I'm not sure one exists or is even a good idea. There are many ways in which this breaks extensibility and goes against the spirit of inheritance. When bar publicly inherits foo, bar is a foo for all practical purposes, and client code shouldn't need to distinguish base class and derived class.
A public typedef in the base class often scratches the itches you might need to have scratched and is clearer:
class foo { public: typedef foo name_making_type; ... };
int main() {
Foo::name_making_type a;
Bar::name_making_type b;
}
What's with the base class? Are you a .NET or Java programmer?
C++ supports multiple inheritance, and also does not have a global common base class. So a C++ type may have zero, one, or many base classes. Use of the definite article is therefore contraindicated.
Since the base class makes no sense, there's no way to find it.
I am looking for a portable resolution for similar problems for months. But I don't find it yet.
G++ has __bases and __direct_bases. You can wrap them in a type list and then access any one of its elements, e.g. a std::tuple with std::tuple_element. See libstdc++'s <tr2/type_traits> for usage.
However, this is not portable. Clang++ currently has no such intrinsics.
With C++11, you can create a intrusive method to always have a base_t member, when your class only inherits from one parent:
template<class base_type>
struct labeled_base : public base_type
{
using base_t = base_type; // The original parent type
using base::base; // Inherit constructors
protected:
using base = labeled_base; // The real parent type
};
struct A { virtual void f() {} };
struct my_class : labeled_base<A>
{
my_class() : parent_t(required_params) {}
void f() override
{
// do_something_prefix();
base_t::f();
// do_something_postfix();
}
};
With that class, you will always have a parent_t alias, to call the parent constructors as if it were the base constructors with a (probably) shorter name, and a base_t alias, to make your class non-aware of the base class type name if it's long or heavily templated.
The parent_t alias is protected to don't expose it to the public. If you don't want the base_t alias is public, you can always inherit labeled_base as protected or private, no need of changing the labeled_base class definition.
That base should have 0 runtime or space overhead since its methods are inline, do nothing, and has no own attributes.
Recently when I reading Unreal Engine source code, I found a piece of code meet your requirement.
Simplified code is below:
#include <iostream>
#include <type_traits>
template<typename T>
struct TGetBaseTypeHelper
{
template<typename InternalType> static typename InternalType::DerivedType Test(const typename InternalType::DerivedType*);
template<typename InternalType> static void Test(...);
using Type = decltype(Test<T>(nullptr));
};
struct Base
{
using DerivedType = Base;
static void Print()
{
std::cout << "Base Logger" << std::endl;
}
};
struct Derived1 : Base
{
using BaseType = typename TGetBaseTypeHelper<Derived1>::Type;
using DerivedType = Derived1;
static void Print()
{
std::cout << "Derived1 Logger" << std::endl;
}
};
struct Derived2 : Derived1
{
using BaseType = typename TGetBaseTypeHelper<Derived2>::Type;
using DerivedType = Derived2;
static void Print()
{
std::cout << "Derived2 Logger" << std::endl;
}
};
int main()
{
Derived1::BaseType::Print();
Derived2::BaseType::Print();
}
Using a macro below to wrap those code make it simple:
#define DECLARE_BASE(T) \
public: \
using BaseType = typename TGetBaseTypeHelper<T>::Type; \
using DerivedType = T;
I got confused when first seeing these code. After I read #Xeo 's answer and #juanchopanza 's answer, I got the point.
Here's the keypoint why it works:
The decltype expression is part of the member declaration, which does
not have access to data members or member functions declared after
it.
For example:
In the declaration of class Derived1, when declaring Derived1::BaseType, Derived1::BaseType doesn't know the existence of Derived1::DerivedType. Because Derived1::BaseType is declared before Derived1::DerivedType. So the value of Derived1::BaseType is Base not Derived1.