Use static_cast in a class hierarchy to enable visitor pattern - c++

Imagine following scenario. I derive from a library class to enable the visitor pattern:
#include <iostream>
#include <vector>
struct MyClassA;
struct MyClassB;
struct MyVisitor{
virtual void visit(MyClassA* c) { std::cout << "My Class A" << std::endl; }
virtual void visit(MyClassB* c) { std::cout << "My Class B" << std::endl; }
};
struct LibClass {};
struct MyClass : public LibClass {
virtual void Accept(MyVisitor& visitor) = 0;
};
struct MyClassA : public MyClass {
virtual void Accept(MyVisitor& visitor) {
visitor.visit(this);
}
};
struct MyClassB : public MyClass {
virtual void Accept(MyVisitor& visitor) {
visitor.visit(this);
}
};
// vector signature can't be changed
void foo(std::vector<LibClass*>& v) {
MyVisitor visitor;
for(auto libC : v) {
auto myC = static_cast<MyClass*>(libC); // questionable line
//auto myC = dynamic_cast<MyClass*>(libC); // don't want to use dynamic cast
myC->Accept(visitor);
}
}
int main() {
// vector signature can't be changed
std::vector<LibClass*> v;
v.push_back(new MyClassA());
v.push_back(new MyClassB());
foo(v);
return 0;
}
The output is as expected:
My Class A
My Class B
This is a question regarding design. In my eyes, it is bad style to use dynamic_cast and should be avoided. As the vector can get quite large, I also want to avoid calls on the iteration to dynamic_cast.
I can be sure, that every pointer in the vector is derived from MyClass.
I want to use the visitor pattern to implement features depending on the derived class, so I will implement derived classes of MyVisitor, too. MyVisitor later could be provide a virtual interface for all possible childrens. The concrete Visitors than can override only that methods, on which children they want to interact with.
So my questions are:
Is there any danger using the static_cast in that way?
Would you consider this a good design under the circumstance, that I want to insert the possibilty to use the visitor pattern?

dynamic_cast is safer (assuming checking for nullptr) as compiler might check at runtime that the class is really what you want. (No compile-time hierarchy check, due to possible multiple inheritance). foo can be used safely (Even by LibClass which are not MyClass).
With static_cast, you do a promise to the compiler. Breaking it would lead to UB.
The only check done at compile time is that derived class (MyClass) is actually in the hierarchy of the base class (LibClass).
foo signature is now misleading, as you expect only MyClass instead of any LibClass.
But as long as you don't break that promise, code is ok.

Related

the member variable with the same name in derived class

UPDATE: the behaviour is not template specific, so
struct Derived : public Base {
OverrideFoo* m_data {new OverrideFoo()};
}
will do the same. so it seems m_data in Derived and m_data in Base both exist in memory layout. If we define a function in Derived,
e.g., Derived::print() { m_data->print()}, this will use m_data in Derived, however, if base function is called on derived object, it still use m_data from Base.
I was surprised with the behaviour of the following code, it prints "from foo", rather than the "from override foo". why is it like this? shouldn't the "m_data" be the type of "OverrideFoo"?
#include <iostream>
using namespace std;
struct Foo {
void print() {
printf("from foo\n");
}
};
struct OverrideFoo {
void print() {
printf("from override foo\n");
}
};
struct Base {
void useData() {
m_data->print();
}
Foo* m_data {new Foo()};
};
template <class t>
struct Derived : public Base {
t* m_data {new t()};
};
int main()
{
Derived<OverrideFoo> d;
d.useData();
return 0;
}
When you call d.useData(), you are calling Base::useData(), which accesses Base::m_data.
I suppose you're expecting Base::useData() to use Derived::m_data, just because the variable has a similar name. However that's not how this works. Both classes get their own independent m_data, and in your case, with different types.
It's true that Derived::m_data hides Base::m_data, which may suggest to you that they are related or that one "overrides" the other. Don't confuse that with hiding. The hiding is a natural consequence of the similar naming. If Derived needs to access Base::m_data, it must qualify it in order to disambiguate from its own m_data.
Note: Member variables / fields cannot be overridden. If you need an override-style behavior, you'll need to do it via a member function (something like virtual IPrintable* GetPrintable(). And the base class must grant the possibility of overriding with the virtual keyword.
Another way to think about this: Base, despite what its name suggests, is a complete type. You can do Base x; to instantiate and use this class, without being derived. The compiler generates code for Base which is complete and functional, including the code to access Base::m_data. If m_data were somehow overrideable, how could this code be generated? What would Base understand sizeof(*m_data) to be, if its datatype could be overridden in some base class? How would the compiler know what m_data even refers to, if you're suggesting it can be changed by any class which derives it?
Another point: If members were able to be overridden by default (without the virtual keyword), it would cause mass chaos for base classes. Imagine writing a generic base class and risking that derived classes could unknowingly change the state of the base? Or imagine writing a derived class and being concerned about your variable naming because "well maybe a base class used the same name?"
So let's summarize the key points:
Fields cannot be overridden, period. It would break sizeof() among lots of other things (whole other topic)
Base classes must explicitly grant derived classes to override member functions via the virtual keyword.
There are probably better ways to do what you're attempting though. The most natural for me would be to specify the Foo type as a template parameter to Base.
Like this:
struct Foo1 {
void print() {
printf("from foo\n");
}
};
struct Foo2 {
void print() {
printf("from override foo\n");
}
};
template<typename TData>
struct Base {
void useData() {
m_data.print();
}
TData m_data;
};
template <typename TData>
struct Derived : public Base<TData> {
};
int main()
{
Derived<Foo1> d1;
d1.useData();
Derived<Foo2> d2;
d2.useData();
return 0;
}
It's hard to know the best approach for you, because this is an unrealistic contrived example.
Try this code out and you will find that the two m_data has different memory address, which means they are different variable.
#include <iostream>
using namespace std;
struct Foo {
void print() {
printf("from foo\n");
}
};
struct OverrideFoo {
void print() {
printf("from override foo\n");
}
};
struct Base {
void useData() {
m_data->print();
std::cout << m_data << std::endl;
}
Foo* m_data {new Foo()};
};
template <class t>
struct Derived : public Base {
t* m_data {new t()};
};
int main()
{
Derived<OverrideFoo> d;
d.useData();
d.m_data->print();
std::cout << d.m_data << std::endl;
return 0;
}

Downcasting best-practice (C++)

Static code analysis tools tend to ramble a lot about "downcasting a base class to a derived class" and I also found a couple of coding standard guides, which mention not to do this so I was wondering what is the best-practice way.
Here's my use case:
I have a Base (interface), DerivedA, DerivedB classes and then an array containing Base pointers.
Then I iterate through the array and based on a flag, I determine if the object is DerivedA or DerivedB, cast it down and do some random stuff to the object from the outside.
Basically something like this:
// arr is of type Base**
for (int i = 0; i < size; ++i)
{
// doMagic has an overload for both types
if (arr[i]->isDerivedA())
{
doMagic(reinterpret_cast<DerivedA*>(arr[i]));
}
else if (arr[i]->isDerivedB())
{
doMagic(reinterpret_cast<DerivedB*>(arr[i]));
}
}
Bout the reinterpret, I cannot use dynamic_cast due to embedded platform restrictions (the same for C++11), but the Base class being an interface guarantees that the object is either DerivedA or DerivedB.
I could make DerivedA and DerivedB only implement pure virtual calls, thus i wouldn't have to worry about downcasting anything, but the DerivedA and DerivedB classes are very much specialized and doMagic does completely different things with the instances...
So I was wondering how you guys approach this - having a single array of very different objects, but inherited from a single base, iterating through them and doing some specialized stuff from the outside.
You probably should try to use visitor pattern.
Here is a simple example:
#include <cstdio>
class A;
class B;
class Visitor {
public:
void visit(A &a) {
printf("Visited A\n");
}
void visit(B &) {
printf("Visited B\n");
}
};
class A {
public:
virtual ~A() { }
virtual void applyVisitor(Visitor &v) {
v.visit(*this);
}
};
class B : public A {
public:
~B() override { }
void applyVisitor(Visitor &v) override {
v.visit(*this);
}
};
int main() {
A a;
B b;
Visitor v;
a.applyVisitor(v);
b.applyVisitor(v);
return 0;
}
If you know that a pointer of a base class points to an object of a derived class, you may use static_cast. The compiler will insert appropriate code to adjust offsets, unlike reinterpret_cast or a C-Cast.

How to ensure that derivative classes implement particular methods, retaining standard layout?

I'm making a base class, which has some methods, which are used in derived classes. This base class is something like an abstract class in the sense that apart from (protected) methods, it defines the interface (i.e. public) methods which must be implemented in derived classes. But it's not intended to be used as a polymorphic base, instead its derivatives will be used as template parameters for some other functions/functors, which would call the interface methods.
Given the above, I could use the usual way of defining abstract classes like using pure virtual functions, but there's a problem with this: the resulting derivative classes are required to have standard layout. Thus no virtual functions allowed. But still there'll be many derivatives, which will not be used until some later time, and I'd like to make the compiler check that all the methods required are implemented with the correct signature (e.g. int Derived::f(double) instead of int Derived::f(float) is not allowed).
What would be a good way to do this, taking into account the requirement of standard layout?
Here's an implementation of the CRTP pattern with a static_assert inside the interface dispatching routine:
#include <iostream>
#include <type_traits>
template<class Derived>
class enable_down_cast
{
typedef enable_down_cast Base;
public:
// casting "down" the inheritance hierarchy
Derived const* self() const { return static_cast<Derived const*>(this); }
Derived* self() { return static_cast<Derived* >(this); }
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~enable_down_cast() = default;
};
template<class FX>
class FooInterface
:
public enable_down_cast< FX >
{
using enable_down_cast< FX >::self; // dependent name now in scope
public:
int foo(double d)
{
static_assert(std::is_same<decltype(self()->do_foo(d)), int>::value, "");
return self()->do_foo(d);
}
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~FooInterface() = default;
};
Note that the above static_assert only fires if the return types of the interface and the implementation don't match. But you can decorate this code with any type trait you wish, and there are plenty of Q&As here on SO that write type traits to check for an exact function signature match between interface and implementation.
class GoodFooImpl
:
public FooInterface< GoodFooImpl >
{
private:
friend class FooInterface< GoodFooImpl > ;
int do_foo(double) { std::cout << "GoodFooImpl\n"; return 0; }
};
class BadFooImpl
:
public FooInterface< BadFooImpl >
{
private:
friend class FooInterface< BadFooImpl >;
char do_foo(double) { std::cout << "BadFooImpl\n"; return 0; }
};
int main()
{
GoodFooImpl f1;
BadFooImpl f2;
static_assert(std::is_standard_layout<GoodFooImpl>::value, "");
static_assert(std::is_standard_layout<BadFooImpl>::value, "");
f1.foo(0.0);
f2.foo(0.0); // ERROR, static_assert fails, char != int
}
Live Example on Coliru. Note that the derived class is indeed standard layout.

Downcasting instance of base class to derived class

I am interested if it is safe, to DOWNCAST (thanks Mike) an instance of a base class to a derived class under certain conditions. I think a sample is the most easy way to explain:
struct BaseA
{
void foo() const {}
double bar_member;
// no virtuals here
};
struct DerivedA : public BaseA
{
double bar(double z) {bar_member = z;return bar_member;}
// DerivedA does not add ANY member variables to BaseA.
// It also does not introduce ANY virtual functions.
};
struct BaseB
{
BaseA baseA;
};
// add extra functionality to B, to do this,
// i also need more functionality on baseA.
struct DerivedB : public BaseB
{
// is this "safe"? since BaseA and DerivedA
// should have the same memory layout?!?
DerivedA& getA() {return *static_cast<DerivedA*>(&baseA);}
double foo(double z) {return getA().bar(z);}
};
#include <iostream>
int main(int argc, char** argv)
{
DerivedB b;
// compiles and prints expected result
std::cout << b.foo(argc) << std::endl;
}
In my case, the classes BaseA and BaseB implement some kind of view concept. However, they also hold all the data members required to add further functionality in the derived classes. I know that I could implement the view to hold only a reference to the class providing the functionality. However, that would comes with some drawbacks:
I need to rewrite the whole interface for the view classes.
In my case, the Derived classes possesses an extra template argument (a callback type), which I want to have erased in the view. Hence, the view must not hold a direct reference to the classes providing functionality.
I tested my code, it works, however, I don't really trust the approach. And yes, I know I could achieve some of this with virtuals etc. but it is really performance critical...
Any ideas, hints, are welcome
Martin
for the interested people:
i changed my design the following way:
struct DerivedB : public BaseB
{
// encapsule the required extended functionality of BaseA member
struct OperateOnBaseA
{
OperateOnBaseA(BaseA& a);
double dosomething(double);
};
OperateOnBaseA a_extension;
DerivedB() :a_extension(baseA) {}
double foo(double z) {return a_extension.dosomething();}
};
As to the technical side: It is of course forbidden by the 2011 standard, 5.2.9.11, static cast. Let B be a base of D:
If the prvalue of type “pointer to cv1 B” points to a B that is actually a subobject of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the cast is undefined.
On the other hand I'd be surprised if somebody could find an implementation which doesn't just do it, because of the obvious implementations of classes, methods and static casts.
Your existing code has undefined behaviour, as stated in the other answers. You can avoid that, if you don't mind some truly horrible code, by destroying the object at baseA and creating a DerivedA at the same location, so the downcast is valid:
#include <new>
struct DerivedB : public BaseB
{
DerivedB()
{
static_assert( sizeof(BaseA) == sizeof(DerivedA), "same size" );
baseA.~BaseA();
::new(&baseA) DerivedA();
}
~DerivedB()
{
getA().~DerivedA();
::new(&baseA) BaseA();
}
DerivedA& getA() {return *static_cast<DerivedA*>(&baseA);}
double foo(double z) {return getA().bar(z);}
};
The destructor restores an object of the original type, so that when the BaseB destructor destroys its baseA member it runs the destructor of the correct type on the object.
But I would avoid doing this and redesign your classes to solve it another way.
I don't find your approad clean enough for what you're trying to do. Assuming there's a "data source type" SourceA and a "data view type" ViewB, I would go more like this:
#include <iostream>
using namespace std;
template<typename T>
class SourceA_base
{
protected:
T data;
public:
using value_type = T;
SourceA_base(T&& a) : data(std::move(a)) { }
SourceA_base(T const& a) : data() { }
void foo() const {}
};
template<typename T>
class SourceA : public SourceA_base<T>
{
using B = SourceA_base<T>;
public:
using B::B;
T bar(T z) { return B::data = z; }
};
template<typename U>
class ViewB_base
{
protected:
U&& source;
public:
using value_type = typename std::remove_reference<U>::type::value_type;
ViewB_base(U&& a) : source(std::forward<U>(a)) { }
};
template<typename U>
class ViewB : public ViewB_base<U>
{
using B = ViewB_base<U>;
using T = typename B::value_type;
public:
using B::B;
T foo(T z) { return B::source.bar(z); }
};
int main ()
{
using S = SourceA<double>;
S a{3.14};
ViewB<S&> b{a};
std::cout << b.foo(6.28) << std::endl; // compiles and prints expected result
std::cout << ViewB<S>{S{2}}.foo(4) << std::endl; // still works
}
That is, all (source/view) types are templated, views contain references, and there are no downcasts. On your reservations for the use of references:
Re-writing the whole interface: No need now, thanks to templates.
Erasing callback types: First, type erasure and performance critical applications are not always good friends. Second, you'd better have the callback erase its own underlying type(s), not the view erase the type of the callback. Each class should do its own job. Or, don't erase types and make them template parameters.
I used rvalue-references so that the whole thing works for temporaries as well, as shown in my second example. Maybe constructors are not always complete/correct here. e.g. for const references; I reality would have fully templated constructors (accepting universal references), but to make this cooperate with one-argument implicitly defined copy/move constructors is a bit trickier (needs type traits and enable_if) and I only wanted to hightlight the idea here.
You may also consider using tuples to hold data, taking advantage of their empty base optimization.
As for your original question, this downcast is something I would never do; for the technical side, see Peter Schneider's answer.

How to force all derived classes to implement a virtual method?

Say you have a base class Dep for a tree of classes. There is a virtual method Dep* Dep::create() that I want to be implemented by every single leaf class. Is there any way to enforce this?
Note: The problem here is that there could be intermediate classes (say class B : public A : public Dep) implementing this method (A::create) by accident or because they think they are leaf classes, but are in fact subclassed themselves.
The question ends here.
Context
If you are curious why I need this; I have a class Master which has Dep objects of unknown concrete type. If Master is duplicated, I need to come up with a matching clone of the Dep instance. Next best thing to do is the virtual constructor idiom, which introduces precisely this problem.
Additionally, I cannot even catch this (other then by crashing horribly), because for obscure reasons, people that have more to say than me, have outlawed dynamic_cast in this project (perhaps this is a good decision; But anyways a completely different discussion).
C++ provides no way to keep a class from inheriting from your class, and there is no way to make a particular class in the inheritance hierarchy implement a method. The only rule is that somewhere in the inheritance hierarchy above a particular class (not necessarily in the leaf) all virtual functions must have an implementation for that class to be instantiatable.
For instance, A could inherit from Def and implement all it's [pure] virtual methods. Then if B inherits from A, it doesn't have to implement anything. There's no way to keep that from happening.
So the answer is no, there is no way to enforce this.
Using curiously recurring template fun, you can achieve something quite similar:
template<typename T>
class Cloneable : public T, public Dep
{
private:
Cloneable<T>() : T() { }
public:
static Cloneable<T>* Create() { return new Cloneable<T>(); }
Cloneable<T>* clone() { return new Cloneable<T>(*this); }
};
Instead of deriving from Dep and instantiating via new MyType, use Cloneable<MyType>::Create. Since Cloneable<MyType> is derived from MyType, you can use the instance the same way you would use any MyType, except that it is now guaranteed to have Dep::clone.
Additionally your Master should not accept an instance of type Dep, but enforce that it is a Cloneable<T>. (Replace your orignial function by a simple function template that enforces this.) This guarantees that any Dep inside the master has a correctly implemented clone function.
Since Cloneable<MyType> has no public constructor, it cannot be inherited, however your actual MyType can be further inherited and used just as before.
Did TPTB outlaw all RTTI, or only dynamic_cast<>()? If you can use RTTI, then you can enforce the existence of the method as a postcondition of calling it:
#include <typeinfo>
#include <cassert>
#include <iostream>
#include <stdexcept>
class Base {
protected:
virtual Base* do_create() = 0;
virtual ~Base() {}
public:
Base* create() {
Base *that = this->do_create();
if( typeid(*this) != typeid(*that) ) {
throw(std::logic_error(std::string() +
"Type: " +
typeid(*this).name() +
" != " +
typeid(*that).name()));
}
return that;
}
};
class Derive1 : public Base {
protected:
Base* do_create() { return new Derive1(*this); }
};
class Derive2 : public Derive1 {};
void f(Base*p) { std::cout << typeid(*p).name() << "\n"; }
int main() {
Derive1 d1;
Base *pD1 = d1.create(); // will succeed with correct semantics
Derive2 d2;
Base *pD2 = d2.create(); // will throw exception due to missing Derive2::do_create()
}
If you control the base class AbstractDep then you can enforce that concrete leaf classes must be created by using a class template WithCloning. This leaf can then be sealed so that it cannot be inherited. Or more precisely, instances cannot be created of a derived class.
class AbstractDep
{
template< class Type > friend class WithCloning;
private:
enum FooFoo {};
virtual FooFoo toBeImplementedByLeafClass() = 0;
public:
virtual AbstractDep* clone() const = 0;
};
template< class Type > class WithCloning;
class Sealed
{
template< class Type > friend class WithCloning;
private:
Sealed() {}
};
template< class Type >
class WithCloning
: public Type
, public virtual Sealed
{
private:
AbstractDep::FooFoo toBeImplementedByLeafClass()
{
return AbstractDep::FooFoo();
}
public:
virtual WithCloning* clone() const
{
return new WithCloning( *this );
}
};
typedef WithCloning<AbstractDep> Dep;
class AbstractDerivedDep
: public AbstractDep
{
// AbstractDep::FooFoo toBeImplementedByLeafClass(); // !Not compile.
public:
};
typedef WithCloning<AbstractDerivedDep> DDep;
struct Foo: Dep {}; // !Does not compile if instantiated.
int main()
{
Dep d;
//Foo f;
}
If the classes require more than default construction then that most be solved additionally.
One solution is then to forward an argument pack from the WithCloning constructor (there is an example C++98 implementation on my blog, and C++0x supports that directly).
Summing up, to be instantiable the class must be WithCloning.
Cheers & hth.,
when you say that they are unknown, i presume they still inherit from a common base class /interface right?
only thing i can think of you can use to force is on the virtual base class add
virtual Base* clone() {
assert( 1==0 ); //needs to be overriden
}
so you are forced to override, but this is only detected at run-time when trying to call clone on a instance of a class that is missing the override
even if you are not allowed to use dynamic_cast or RTTI, you can still enable it for debug purposes locally on your build, if that will help you find the typeid of offending classes
it sounds like you are familiar with the clone pattern, but i'll post it quietly in here, and we can forget about it:
http://www.cplusplus.com/forum/articles/18757/