How can I switch element and container types for purpose of benchmarking, without producing a large number of test client applications? - c++

I have a ClientInterface class, that uses the Strategy pattern to organize two complex algorithms conforming to interfaces Abase and Bbase, respectively. The ClientInterface agglomerates (via composition) the data on which the algorithms operate, which needs to conform to the Data interface.
What I tried to do is to have a single ClientInterface class, which is able to choose different Strategies and Data implementations at run-time. The algorithms and data implementations are chosen using the Factory Method which reads the strings from an input file and selects the algorithm and data implementation in the ClientInterface constructor. The run-time choice of data and algorithms is not provided in the code model below.
The Data implementation can be based on a map, a list, an unordered_map , etc. to test how does the efficiency of two complex algorithms (Abase and Bbase implemented Strategies) change with different containers used for the Data.
Additionally, the Data agglomerates different Elements (ElementBase implementations). Different element implementations will also have significant impact on the efficiency of theh ClientInterface, but the Elements are really disjoint types with implementations coming from different libraries. I know this for a fact, since profiling the existing application shows the Element operation to be one of the bottlenecks.
I know that if I use polymorphism with containers, there is "boost/ptr_container" out there, but the Data will store hundreds of thousands, if not millions of Elements. Using polymorphism for Elements in this case will have a significant overhead on the ClientInterface, but if I choose to make data a class Template for the Element type, I will end up statically defining the ClientInterface class, which means producing a client application per each Element type at least.
Can I assume that for the same number of Elements and the ClientInterface configuration obtained at run-time, the overhead induced by the use of polymorphism for the Element type will have the same impact on all configurations of the Data and Algorithm implementations? In this case, I can run the automated tests, decide on the configuration of the Data implementation and the Element implementation, and define a statically configured EfficientClientInterface to be used in the productive code?
Goal: I have a test harness prepared, and what I am trying to do is to automatize the testing on the family of test cases, since changing the Algorithms and Elements at run-time, allows me to use a single application in a loop, which is configured at run-time and whose output is measured for efficiency. In the real implementation, I am dealing with at least 6 algorithm interfaces, 3-4 Data implementations, and I estimate 3 Element implementations at least.
So, my questions are:
1) How can an Element support different operations when overloading is not working for return types? If I make the operation a template, it needs to be defined at compile-time, which messes with my automated testing procedure.
2) How can I design this code better to achieve the goal?
3) Is there a better overall approach to this problem?
Here is the code model:
#include <iostream>
#include <memory>
class ElementOpResultFirst
{};
class ElementOpResultSecond
{};
class ElementBase
{
public:
// Overloading does not allow different representation of the solution for the element operation.
virtual ElementOpResultFirst elementOperation() = 0;
//virtual ElementOpResultSecond elementOperation() = 0;
};
class InterestingElement
:
public ElementBase
{
public:
ElementOpResultFirst elementOperation()
{
// Implementation dependant operation code.
return ElementOpResultFirst();
}
//ElementOpResultSecond elementOperation()
//{
//// Implementation dependant operation code.
//return ElementOpResultSecond();
//}
};
class EfficientElement
:
public ElementBase
{
public:
ElementOpResultFirst elementOperation()
{
// Implementation dependant operation code.
return ElementOpResultFirst();
}
//ElementOpResultSecond elementOperation()
//{
//// Implementation dependant operation code.
//return ElementOpResultSecond();
//}
};
class Data
{
public:
virtual void insertElement(const ElementBase&) = 0;
virtual const ElementBase& getElement(int key) = 0;
};
class DataConcreteMap
:
public Data
{
// Map implementation
public:
void insertElement(const ElementBase&)
{
// Insert element into the Map implementation.
}
const ElementBase& getElement(int key)
{
// Get element from the Map implementation.
}
};
class DataConcreteVector
:
public Data
{
// Vector implementation
public:
void insertElement(const ElementBase&)
{
// Insert element into the vector implementation.
}
const ElementBase& getElement(int key)
{
// Get element from the Vector implementation
}
};
class Abase
{
public:
virtual void aFunction() = 0;
};
class Aconcrete
:
public Abase
{
public:
virtual void aFunction()
{
std::cout << "Aconcrete::function() " << std::endl;
}
};
class Bbase
{
public:
virtual void bFunction(Data& data) = 0;
};
class Bconcrete
:
public Bbase
{
public:
virtual void bFunction(Data& data)
{
data.getElement(0);
std::cout << "Bconcrete::function() " << std::endl;
}
};
// Add a static abstract factory for algorithm and data generation.
class ClientInterface
{
std::unique_ptr<Data> data_;
std::unique_ptr<Abase> algorithmA_;
std::unique_ptr<Bbase> algorithmB_;
public:
ClientInterface()
:
// A Factory Method is defined for Data, Abase and Bbase that
// produces the concrete type based on an entry in a text-file.
data_ (std::unique_ptr<Data> (new DataConcreteMap())),
algorithmA_(std::unique_ptr<Abase> (new Aconcrete())),
algorithmB_(std::unique_ptr<Bbase> (new Bconcrete()))
{}
void aFunction()
{
return algorithmA_->aFunction();
}
void bFunction()
{
return algorithmB_->bFunction(*data_);
}
};
// Single client code: both for testing and final version.
int main()
{
ClientInterface cli;
cli.aFunction();
cli.bFunction();
return 0;
};

What I tried to do is to have a single ClientInterface class, which is
able to choose different Strategies and Data implementations at
run-time. The algorithms and data implementations are chosen using the
Factory Method which reads the strings from an input file and selects
the algorithm and data implementation in the ClientInterface
constructor. The run-time choice of data and algorithms is not
provided in the code model below.
Sounds like you have the basis for some of it here: Either just produce a set of files to test with that produce the right different sets of inputs. Or refactor the Factory function so that the reading of the file and the strings are separate, so you can call your factory function [internals] with a a string from the code.
Can I assume that for the same number of Elements and the
ClientInterface configuration obtained at run-time, the overhead
induced by the use of polymorphism for the Element type will have the
same impact on all configurations of the Data and Algorithm
implementations? In this case, I can run the automated tests, decide
on the configuration of the Data implementation and the Element
implementation, and define a statically configured
EfficientClientInterface to be used in the productive code?
I don't think you can make that assumption. Different implementations may well have different effects on the algorithms - copying a 100 byte string is significantly harder than copying a 4 byte integer, for example. So what the data is, and how it's organized will have some effect on the work you do. Of course, since you haven't described in much detail what your Elements actually contain, it's all guesswork.
1) How can an Element support different operations when overloading is
not working for return types? If I make the operation a template, it
needs to be defined at compile-time, which messes with my automated
testing procedure.
Make a factory class that returns an ElementBase reference or pointer? That's my immediate reaction to this question, but again, the detail in your question is sufficiently vague that it's hard to say for sure.
In the real application, how does this work? Is it done by templates, then you'd better implement the testcode by templates, and fill it out with a selection of realistic variations on what you think the real system is likely to do.
2) How can I design this code better to achieve the goal?
Try to reuse the production code?
3) Is there a better overall approach to this problem?
Not sure yet.

Related

How to create structs that all implement a trait that have common data members? [duplicate]

I'm trying to implement the Rust equivalent code of the following C++ code which makes use of inheritance, but got stuck. This is my sample code:
class Vehicle {
public:
double lat;
double lon;
double alt;
double speed;
};
class CabVehicle : public Vehicle {
};
class PackerMoverVehicle : public Vehicle {
};
int main() {
CabVehicle cv;
cv.lat = 12.34;
cv.lon = 12.34;
cv.alt = 12.34;
PackerMoverVehicle pmv;
pmv.lat = 12.34;
pmv.lon = 12.34;
pmv.alt = 12.34;
}
How should this be written in Rust?
The general answer is to use composition instead of inheritance. Depending on the application, there can be different ways the composition should go. In most cases, you should start with
struct VehicleState {
lat: f64,
lon: f64,
alt: f64,
speed: f64,
}
The remaining question then is how your different types of vehicles are going to be used.
Way 1: If different parts of the code use the different types of vehicles in distinct, non-overlapping ways, you might simply contain the state struct in the specific structs:
struct Cab {
state: VehicleState,
// ... other fields
}
struct PackerMover {
state: VehicleState,
// ... other fields
}
This is the version most directly analogous to C++ inheritance, particularly in memory layout and in static typing. However, this makes it awkward to access the common state for different vehicles, and it does not support dynamic dispatch, unless you write a trait with a method to access state (which comes with some limitations in the kinds of code you can write). You should generally avoid this approach unless you know you don't need anything else.
Way 2: If there is code which should be generic over which kind of vehicle is in use, but this is statically decided, you might make a generic struct:
struct Vehicle<T> {
state: VehicleState,
details: T,
}
struct Cab { /* ... */ }
struct PackerMover { /* ... */ }
/// This function only works with Cabs
fn foo(vehicle: Vehicle<Cab>) { /* ... */ }
/// This function works with any Vehicle
fn foo<T>(vehicle: Vehicle<T>) { /* ... */ }
This makes it easy to access the state, and all usage is statically dispatched.
It can be dynamically dispatched too if you make one small change to Vehicle and add a trait:
struct Vehicle<T: ?Sized> { /* ... */
// ^^^^^^^^ remove default restriction on the type parameter
trait VehicleDetails { /* add methods here */ }
impl VehicleDetails for Cab { /* ... */ }
impl VehicleDetails for PackerMover { /* ... */ }
This allows you to coerce a reference (or pointer or Box too) &Vehicle<Cab> into &Vehicle<dyn VehicleDetails>, which is a type that a pointer to any Vehicle whose T implements VehicleDetails. This can be used to put a variety of vehicles in a Vec<Box<Vehicle<dyn VehicleDetails>>>, for example. Using dyn causes dispatch through vtables, like C++ virtual methods.
(Info on this language feature. The documentation says that “custom DSTs are a largely half-baked feature for now” but this particular case is exactly the case where they do work without any trouble.)
This is not a good choice if you want to be able to find out which “subclass” is being used and interact with it specifically; it is a good choice if all particular characteristics of the vehicle can be expressed within the VehicleDetails trait.
Way 3: If the application is going to be routinely working with dynamically-chosen vehicle types — especially if it frequently wants to ask the question “is this vehicle a Cab” and then interact with its Cabness — then you should probably use an enum to contain the details.
struct Vehicle {
state: VehicleState,
kind: VehicleKind,
}
enum VehicleKind {
Cab {
seats: u16,
},
PackerMover {
cargo_capacity: u64,
}
}
This is dynamically dispatched in the sense that every Vehicle can be any kind, so you can always mix-and-match vehicle kinds, but without involving any pointers or vtables. The main disadvantage is that extending it to new kinds requires modifying the single enum VehicleKind, so this is not suitable for a library whose users would be writing subclasses in C++. However, this is a lot less fiddly to work with than the Vehicle<dyn VehicleDetails> I mentioned above.
Rust is basically more like a procedural and a functional language with some pseudo-OO features, it’s simultaneously lower-level and more abstract than C++ (closer to C or even to C—, but with ZCA and stronger typing). The answer is: there’s no inheritance in Rust, use composition or just rewrite the whole structure. This may look wild for you, but after some time you will understand that there’s no need in inheritance.

Use case of dynamic_cast

In many places you can read that dynamic_cast means "bad design". But I cannot find any article with appropriate usage (showing good design, not just "how to use").
I'm writing a board game with a board and many different types of cards described with many attributes (some cards can be put on the board). So I decided to break it down to the following classes/interfaces:
class Card {};
class BoardCard : public Card {};
class ActionCard : public Card {};
// Other types of cards - but two are enough
class Deck {
Card* draw_card();
};
class Player {
void add_card(Card* card);
Card const* get_card();
};
class Board {
void put_card(BoardCard const*);
};
Some guys suggested that I should use only one class describing a card. But I would mean many mutually excluding attributes. And in the case of the Board class' put_card(BoardCard const&) - it is a part of the interface that I cannot put any card on the board. If I had only one type of card I would have to check it inside the method.
I see the flow like the following:
a generic card is in the deck (it's not important what its type is)
a generic card is drawn from the deck and given to a player (the same as above)
if a player chosen a BoardCard then it can be put on the board
So I use dynamic_cast before putting a card on the board. I think that using some virtual method is out of the question in this case (additionally I wouldn't make any sense to add some action about board to every card).
So my question is: What have I designed badly? How could I avoid dynamic_cast? Using some type attribute and ifs would be a better solution...?
P.S.
Any source treating about dynamic_cast usage in the context of design is more than appreciated.
Yes, dynamic_cast is a code smell, but so is adding functions that try to make it look like you have a good polymorphic interface but are actually equal to a dynamic_cast i.e. stuff like can_put_on_board. I'd go as far as to say that can_put_on_board is worse - you're duplicating code otherwise implemented by dynamic_cast and cluttering the interface.
As with all code smells, they should make you wary and they don't necessarily mean that your code is bad. This all depends on what you're trying to achieve.
If you're implementing a board game that will have 5k lines of code, two categories of cards, then anything that works is fine. If you're designing something larger, extensible and possibly allowing for cards being created by non-programmers (whether it's an actual need or you're doing it for research) then this probably won't do.
Assuming the latter, let's look at some alternatives.
You could put the onus of applying the card properly to the card, instead of some external code. E.g. add a play(Context& c) function to the card (the Context being a means to access the board and whatever may be necessary). A board card would know that it may only be applied to a board and a cast would not be necessary.
I would entirely give up using inheritance however. One of its many issues is how it introduces a categorisation of all cards. Let me give you an example:
you introduce BoardCard and ActionCard putting all cards in these two buckets;
you then decide that you want to have a card that can be used in two ways, either as an Action or a Board card;
let's say you solved the issue (through multiple-inheritance, a BoardActionCard type, or any different way);
you then decide you want to have card colours (as in MtG) - how do you do this? Do you create RedBoardCard, BlueBoardCard, RedActionCard etc?
Other examples of why inheritance should be avoided and how to achieve runtime polymorphism otherwise you may want to watch Sean Parent's excellent "Inheritance is the Base Class of Evil" talk. A promising looking library that implements this sort of polymorphism is dyno, I have not tried it out yet though.
A possible solution might be:
class Card final {
public:
template <class T>
Card(T model) :
model_(std::make_shared<Model<T>>(std::move(model)))
{}
void play(Context& c) const {
model_->play(c);
}
// ... any other functions that can be performed on a card
private:
class Context {
public:
virtual ~Context() = default;
virtual void play(Context& c) const = 0;
};
template <class T>
class Model : public Context {
public:
void play(Context& c) const override {
play(model_, c);
// or
model_.play(c);
// depending on what contract you want to have with implementers
}
private:
T model_;
};
std::shared_ptr<const Context> model_;
};
Then you can either create classes per card type:
class Goblin final {
void play(Context& c) const {
// apply effects of card, e.g. take c.board() and put the card there
}
};
Or implement behaviours for different categories, e.g. have a
template <class T>
void play(const T& card, Context& c);
template and then use enable_if to handle it for different categories:
template <class T, class = std::enable_if<IsBoardCard_v<T>>
void play(const T& card, Context& c) {
c.board().add(Card(card));
}
where:
template <class T>
struct IsBoardCard {
static constexpr auto value = T::IS_BOARD_CARD;
};
template <class T>
using IsBoardCard_v = IsBoardCard<T>::value;
then defining your Goblin as:
class Goblin final {
public:
static constexpr auto IS_BOARD_CARD = true;
static constexpr auto COLOR = Color::RED;
static constexpr auto SUPERMAGIC = true;
};
which would allow you to categorise your cards in many dimensions also leaving the possibility to entirely specialise the behaviour by implementing a different play function.
The example code uses std::shared_ptr to store the model, but you can definitely do something smarter here. I like to use a static-sized storage and only allow Ts of a certain maximum size and alignment to be used. Alternatively you could use a std::unique_ptr (which would disable copying though) or a variant leveraging small-size optimisation.
Why not use dynamic_cast
dynamic_cast is generally disliked because it can be easily abused to completely break the abstractions used. And it is not wise to depend on specific implementations. Of course it may needed, but really rarely, so nearly everyone takes a rule of thumb - probably you should not use it. It's a code smell that may imply that you should rethink Your abstractions because they may be not the ones needed in Your domain. Maybe in Your game the Board should not have put_card method - maybe instead card should have method play(const PlaySpace *) where Board implements PlaySpace or something like that. Even CppCoreGuidelines discourage using dynamic_cast in most cases.
When use
Generally few people ever have problems like this but I came across it multiple times already. The problem is called Double (or Multiple) Dispatch. Here is pretty old, but quite relevant article about double dispatch (mind the prehistoric auto_ptr):
http://www.drdobbs.com/double-dispatch-revisited/184405527
Also Scott Meyers in one of his books wrote something about building double dispatch matrix with dynamic_cast. But, all in all, these dynamic_casts are 'hidden` inside this matrix - users don't know what kind of magic happens inside.
Noteworthy - multiple dispatch is also considered code smell :-).
Reasonable alternative
Check out the visitor pattern. It can be used as replace for dynamic_cast but it is also some kind of code smell.
I generally recommend using dynamic_cast and visitor as a last resort tools for design problems as they break abstraction which increases complexity.
You could apply the principles behind Microsoft's COM and provide a series of interfaces, with each interface describing a set of related behaviors. In COM you determine if a specific interface is available by calling QueryInterface, but in modern C++ dynamic_cast works similarly and is more efficient.
class Card {
virtual void ~Card() {} // must have at least one virtual method for dynamic_cast
};
struct IBoardCard {
virtual void put_card(Board* board);
};
class BoardCard : public Card, public IBoardCard {};
class ActionCard : public Card {};
// Other types of cards - but two are enough
class Deck {
Card* draw_card();
};
class Player {
void add_card(Card* card);
Card const* get_card();
};
class Board {
void put_card(Card const* card) {
const IBoardCard *p = dynamic_cast<const IBoardCard*>(card);
if (p != null) p->put_card(this);
};
That may be a bad example, but I hope you get the idea.
It seems to me that the two types of cards are quite different. The things a board card and an action card can do are mutually exclusive, and the common thing is just that they can be drawn from the deck. Moreover, that's not a thing a card does, it's a player / deck action.
If this is true, a question one should ask is whether they should really descend from a common type, Card. An alternative design would be that of a tagged union: let Card instead be a std::variant<BoardCard, ActionCard...>, and contain an instance of the appropriate type. When deciding what to do with the card, you use a switch on the index() and then std::get<> only the appropriate type. This way you don't need any *_cast operator, and get a complete freedom of what methods (neither of which would make sense for the other types) each type of card supports.
If it's only almost true but not for all types, you can variate slightly: only group together those types of cards that can sensibly be superclassed, and put the set of those common types into the variant.
I always found the usage of a cast a code smell, and in my experience, the 90% of the time the cast was due to bad design.
I saw usage of dynamic_cast in some time-critical application where it was providing more performance improvement than inherit from multiple interfaces or retrieving an enumeration of some kind from the object (like a type). So the code smelt, but the usage of the dynamic cast was worth it in that case.
That said, I will avoid dynamic cast in your case as well as multiple inheritances from different interfaces.
Before reaching my solution, your description sounds like there are a lot of details omitted about the behavior of the cards or the consequence they have on the board
and the game itself. I used that as a further constraint, trying to keep thing boxed and maintainable.
I would go for a composition instead of an inheritance. It will provide you evenly the chance of using the card as a 'factory':
it can spawn more game modifiers - something to be applied to the board, and one to a specific enemy
the card can be reused - the card could stays in the hands of the player and the effect on the game is detached from it (there is no 1-1 binding between cards and effects)
the card itself can sit back on the deck, while the effects of what it did are still alive on the board.
a card can have a representation (drawing methods) and react to the touch in a way, where instead the BoardElement can be evenly a 3d miniature with animation
See [https://en.wikipedia.org/wiki/Composition_over_inheritance for further details]. I'd like to quote:
Composition also provides a more stable business domain in the long term as it is less prone to the quirks of the family members.In other words, it is better to compose what an object can do (HAS - A) than extend what it is(IS - A).[1]
A BoardCard/Element can be something like this:
//the card placed on the board.
class BoardElement {
public:
BoardElement() {}
virtual ~BoardElement() {};
//up to you if you want to add a read() methods to read data from the card description (XML / JSON / binary data)
// but that should not be part of the interface. Talking about a potential "Wizard", it's probably more related to the WizardCard - WizardElement relation/implementation
//some helpful methods:
// to be called by the board when placed
virtual void OnBoard() {}
virtual void Frame(const float time) { /*do something time based*/ }
virtual void Draw() {}
// to be called by the board when removed
virtual void RemovedFromBoard() {}
};
the Card could represent something to be used in a deck or in the user's hands, I'll add an interface of that kind
class Card {
public:
Card() {}
virtual ~Card() {}
//that will be invoked by the user in order to provide something to the Board, or NULL if nothing should be added.
virtual std::shared_ptr<BoardElement*> getBoardElement() { return nullptr; }
virtual void Frame(const float time) { /*do something time based*/ }
virtual void Draw() {}
//usefull to handle resources or internal states
virtual void OnUserHands() {}
virtual void Dropped() {}
};
I'd like to add that this pattern allows many tricks inside the getBoardElement() method, from acting as a factory (so something should be spawned with its own lifetime),
returning an Card data member such as a std:shared_ptr<BoardElement> wizard3D; (as example), create a binding between the Card and the BoardElement as for:
class WizardBoardElement : public BoardElement {
public:
WizardBoardElement(const Card* owner);
// other members omitted ...
};
The binding can be useful in order to read some configuration data or whatever...
So inheritance from Card and from BoardElement will be used to implement the features exposed by the base classes and not for providing other methods that can be reached only through a dynamic_cast.
For completeness:
class Player {
void add(Card* card) {
//..
card->OnUserHands();
//..
}
void useCard(Card* card) {
//..
//someway he's got to retrieve the board...
getBoard()->add(card->getBoardElement());
//..
}
Card const* get_card();
};
class Board {
void add(BoardElement* el) {
//..
el->OnBoard();
//..
}
};
In that way, we have no dynamic_cast, Player and board do simple things without knowing about the inner details of the card they are handled, providing good separations between the different objects and increasing maintainability.
Talking about the ActionCard, and about "effects" that may be applied to other players or your avatar, we can think about having a method like:
enum EffectTarget {
MySelf, //a player on itself, an enemy on itself
MainPlayer,
Opponents,
StrongOpponents
//....
};
class Effect {
public:
//...
virtual void Do(Target* target) = 0;
//...
};
class Card {
public:
//...
struct Modifiers {
EffectTarget eTarget;
std::shared_ptr<Effect> effect;
};
virtual std::vector<Modifiers> getModifiers() { /*...*/ }
//...
};
class Player : public Target {
public:
void useCard(Card* card) {
//..
//someway he's got to retrieve the board...
getBoard()->add(card->getBoardElement());
auto modifiers = card->getModifiers();
for each (auto modifier in modifiers)
{
//this method is supposed to look at the board, at the player and retrieve the instance of the target
Target* target = getTarget(modifier.eTarget);
modifier.effect->Do(target);
}
//..
}
};
That's another example of the same pattern to apply the effects from the card, avoiding the cards to know details about the board and it's status, who is playing the card, and keep the code in Player pretty simple.
Hope this may help,
Have a nice day,
Stefano.
What have I designed badly?
The problem is that you always need to extend that code whenever a new type of Card is introduced.
How could I avoid dynamic_cast?
The usual way to avoid that is to use interfaces (i.e. pure abstract classes):
struct ICard {
virtual bool can_put_on_board() = 0;
virtual ~ICard() {}
};
class BoardCard : public ICard {
public:
bool can_put_on_board() { return true; };
};
class ActionCard : public ICard {
public:
bool can_put_on_board() { return false; };
};
This way you can simply use a reference or pointer to ICard and check, if the actual type it holds can be put on the Board.
But I cannot find any article with appropriate usage (showing good design, not just "how to use").
In general I'd say there aren't any good, real life use cases for dynamic cast.
Sometimes I have used it in debug code for CRTP realizations like
template<typename Derived>
class Base {
public:
void foo() {
#ifndef _DEBUG
static_cast<Derived&>(*this).doBar();
#else
// may throw in debug mode if something is wrong with Derived
// not properly implementing the CRTP
dynamic_cast<Derived&>(*this).doBar();
#endif
}
};
I think that I would end up with something like this (compiled with clang 5.0 with -std=c++17). I'm couroius about your comments. So whenever I want to handle different types of Cards I need to instantiate a dispatcher and supply methods with proper signatures.
#include <iostream>
#include <typeinfo>
#include <type_traits>
#include <vector>
template <class T, class... Args>
struct any_abstract {
static bool constexpr value = std::is_abstract<T>::value || any_abstract<Args...>::value;
};
template <class T>
struct any_abstract<T> {
static bool constexpr value = std::is_abstract<T>::value;
};
template <class T, class... Args>
struct StaticDispatcherImpl {
template <class P, class U>
static void dispatch(P* ptr, U* object) {
if (typeid(*object) == typeid(T)) {
ptr->do_dispatch(*static_cast<T*>(object));
return;
}
if constexpr (sizeof...(Args)) {
StaticDispatcherImpl<Args...>::dispatch(ptr, object);
}
}
};
template <class Derived, class... Args>
struct StaticDispatcher {
static_assert(not any_abstract<Args...>::value);
template <class U>
void dispatch(U* object) {
if (object) {
StaticDispatcherImpl<Args...>::dispatch(static_cast<Derived *>(this), object);
}
}
};
struct Card {
virtual ~Card() {}
};
struct BoardCard : Card {};
struct ActionCard : Card {};
struct Board {
void put_card(BoardCard const& card, int const row, int const column) {
std::cout << "Putting card on " << row << " " << column << std::endl;
}
};
struct UI : StaticDispatcher<UI, BoardCard, ActionCard> {
void do_dispatch(BoardCard const& card) {
std::cout << "Get row to put: ";
int row;
std::cin >> row;
std::cout << "Get row to put:";
int column;
std::cin >> column;
board.put_card(card, row, column);
}
void do_dispatch(ActionCard& card) {
std::cout << "Handling action card" << std::endl;
}
private:
Board board;
};
struct Game {};
int main(int, char**) {
Card* card;
ActionCard ac;
BoardCard bc;
UI ui;
card = &ac;
ui.dispatch(card);
card = &bc;
ui.dispatch(card);
return 0;
}
As I can't see why you wouldn't use virtual methods, I'm just gonna present, how I would do it. First I have the ICard interface for all cards. Then I would distinguish, between the card types (i.e. BoardCard and ActionCard and whatever cards you have). And All the cards inherit from either one of the card types.
class ICard {
virtual void put_card(Board* board) = 0;
virtual void accept(CardVisitor& visitor) = 0; // See later, visitor pattern
}
class ActionCard : public ICard {
void put_card(Board* board) final {
// std::cout << "You can't put Action Cards on the board << std::endl;
// Or just do nothing, if the decision of putting the card on the board
// is not up to the user
}
}
class BoardCard : public ICard {
void put_card(Board* board) final {
// Whatever implementation puts the card on the board, mb something like:
board->place_card_on_board(this);
}
}
class SomeBoardCard : public BoardCard {
void accept(CardVisitor& visitor) final { // visitor pattern
visitor.visit(this);
}
void print_information(); // see BaseCardVisitor in the next code section
}
class SomeActionCard : public ActionCard {
void accept(CardVisitor& visitor) final { // visitor pattern
visitor.visit(this);
}
void print_information(); // see BaseCardVisitor
}
class Board {
void put_card(ICard* const card) {
card->put_card(this);
}
void place_card_on_board(BoardCard* card) {
// place it on the board
}
}
I guess the user has to know somehow what card he has drawn, so for that I would implement the visitor pattern. You could also place the accept-method, which I placed in the most derived classes/cards, in the card types (BoardCard, ActionCard), depeneding on where you want to draw the line on what information shall be given to the user.
template <class T>
class BaseCardVisitor {
void visit(T* card) {
card->print_information();
}
}
class CardVisitor : public BaseCardVisitor<SomeBoardCard>,
public BaseCardVisitor<SomeActionCard> {
}
class Player {
void add_card(ICard* card);
ICard const* get_card();
void what_is_this_card(ICard* card) {
card->accept(visitor);
}
private:
CardVisitor visitor;
};
Hardly a complete answer but just wanted to pitch in with an answer similar to Mark Ransom's but just very generally speaking, I've found downcasting to be useful in cases where duck typing is really useful. There can be certain architectures where it is very useful to do things like this:
for each object in scene:
{
if object can fly:
make object fly
}
Or:
for each object in scene that can fly:
make object fly
COM allows this type of thing somewhat like so:
for each object in scene:
{
// Request to retrieve a flyable interface from
// the object.
IFlyable* flyable = object.query_interface<IFlyable>();
// If the object provides such an interface, make
// it fly.
if (flyable)
flyable->fly();
}
Or:
for each flyable in scene.query<IFlyable>:
flyable->fly();
This implies a cast of some form somewhere in the centralized code to query and obtain interfaces (ex: from IUnknown to IFlyable). In such cases, a dynamic cast checking run-time type information is the safest type of cast available. First there might be a general check to see if an object provides the interface that doesn't involve casting. If it doesn't, this query_interface function might return a null pointer or some type of null handle/reference. If it does, then using a dynamic_cast against RTTI is the safest thing to do to fetch the actual pointer to the generic interface (ex: IInterface*) and return IFlyable* to the client.
Another example is entity-component systems. In that case instead of querying abstract interfaces, we retrieve concrete components (data):
Flight System:
for each object in scene:
{
if object.has<Wings>():
make object fly using object.get<Wings>()
}
Or:
for each wings in scene.query<Wings>()
make wings fly
... something to this effect, and that also implies casting somewhere.
For my domain (VFX, which is somewhat similar to gaming in terms of application and scene state), I've found this type of ECS architecture to be the easiest to maintain. I can only speak from personal experience, but I've been around for a long time and have faced many different architectures. COM is now the most popular style of architecture in VFX and I used to work on a commercial VFX application used widely in films and games and archviz and so forth which used a COM architecture, but I've found ECS as popular in game engines even easier to maintain than COM for my particular case*.
One of the reasons I find ECS so much easier is because the bulk of the systems in this domain like PhysicsSystem, RenderingSystem, AnimationSystem, etc. boil down to just data transformers and the ECS model just fits beautifully for that purpose without abstractions getting in the way. With COM in this domain, the number of subtypes implementing an interface like a motion interface like IMotion might be in the hundreds (ex: a PointLight which implements IMotion along with 5 other interfaces), requiring hundreds of classes implementing different combinations of COM interfaces to maintain individually. With the ECS, it uses a composition model over inheritance, and reduces those hundreds of classes down to just a couple dozen simple component structs which can be combined in endless ways by the entities that compose them, and only a handful of systems have to provide behavior: everything else is just data which the systems loop through as input to then provide some output.
Between legacy codebases that used a bunch of global variables and brute force coding (ex: sprinkling conditionals all over the place instead of using polymorphism), deep inheritance hierarchies, COM, and ECS, in terms of maintainability for my particular domain, I'd say ECS > COM, while deep inheritance hierarchies and brute force coding with global variables all over the place were both incredibly hard to maintain (OOP using deep inheritance with protected data fields is almost as hard to reason about in terms of maintaining invariants as a boatload of global variables IMO, but further can invite the most nightmarish cascading changes spilling across entire hierarchies if designs need to change -- at least the brute force legacy codebase didn't have the cascading problem since it was barely reusing any code to begin with).
COM and ECS are somewhat similar except with COM, the dependencies flow towards central abstractions (COM interfaces provided by COM objects, like IFlyable). With an ECS, the dependencies flow towards central data (components provided by ECS entities, like Wings). At the heart of both is often the idea that we have a bunch of non-homogeneous objects (or "entities") of interest whose provided interfaces or components are not known in advance, since we're accessing them through a non-homogeneous collection (ex: a "Scene"). As a result we need to discover their capabilities at runtime when iterating through this non-homogeneous collection by either querying the collection or the objects individually to see what they provide.
Either way, both involve some type of centralized casting to retrieve either an interface or a component from an entity, and if we have to downcast, then a dynamic_cast is at least the safest way to do that which involves runtime type checking to make sure the cast is valid. And with both ECS and COM, you generally only need one line of code in the entire system which performs this cast.
That said, the runtime checking does have a small cost. Typically if dynamic_cast is used in COM and ECS architectures, it's done in a way so that a std::bad_cast should never be thrown and/or that dynamic_cast itself never returns nullptr (the dynamic_cast is just a sanity check to make sure there are no internal programmer errors, not as a way to determine if an object inherits a type). Another type of runtime check is made to avoid that (ex: just once for an entire query in an ECS when fetching all PosAndVelocity components to determine which component list to use which is actually homogeneous and only stores PosAndVelocity components). If that small runtime cost is non-negligible because you're looping over a boatload of components every frame and doing trivial work to each, then I found this snippet useful from Herb Sutter in C++ Coding Standards:
template<class To, class From> To checked_cast(From* from) {
assert( dynamic_cast<To>(from) == static_cast<To>(from) && "checked_cast failed" );
return static_cast<To>(from);
}
template<class To, class From> To checked_cast(From& from) {
assert( dynamic_cast<To>(from) == static_cast<To>(from) && "checked_cast failed" );
return static_cast<To>(from);
}
It basically uses dynamic_cast as a sanity check for debug builds with an assert, and static_cast for release builds.

Is it a good practice to define algorithm parameter settings as an independent class in C++?

I was wondering whether it was a good practice to define algorithm parameter settings as an independent class. I illustrate my question with the following codes:
using namespace std;
class Parameters
{
public:
Parameters():a_para_(0),b_para_(0) {};
~Parameters() {};
Parameters(const Parameters &para)
{
a_para_ = para.a_para_;
b_para_ = para.b_para_;
}
void set_a_parameter(int a)
{
a_para_ = a;
}
void set_b_parameter(int b)
{
b_para_ = b;
}
private:
int a_para_;
int b_para_;
};
class Algorithm
{
public:
Algorithm() {};
~Algorithm() {};
void set(const Parameters &para)
{
para_ = para;
}
void run()
{
}
private:
Parameters para_;
};
int main()
{
Parameters para;
para.set_a_parameter(3);
para.set_b_parameter(4);
Algorithm fun;
fun.set(para);
fun.run();
return 0;
}
The philosophy behind is that the parameter setting and algorithm implementation can be separated. I discussed this design strategy with an experienced programmer, and it seems that he prefer that the parameter setting and the algorithm should be mixed together as one class. I am therefore writing here for your advice: which one is better? Thanks!
Your question is very general, and there's no general answer. It depends on the situation.
Often times you want to be able to decide at compile time the parameters of your algorithm (for instance, the size of a given buffer, or the dimension of a matrix, or the arity of a tree nodes). Usually these parameters don't change for the lifetime of your algorithm "instance", so to speak. In this context, it is usually good practice to turn your algorithm class into a template, and make these parameters the template parameters.
If the parameters must change during the algorithm lifetime, but their implementation are trivial, there's no need to externalize them. If they are non trivial, and their implementation details may change the algorithm performance (ex: a matrix implementation based on arrays for dense matrices, or on linked lists for sparse ones), then I suppose that you could externalize that parameter.
I think you should ask a more specific question if you want to get a better answer.

Pattern for storing multiple types of struct in a C++ std::<vector> container

I have a data structure which represents a train, which can be made up of many types of car, for example the train engines, a grain car, a passenger car, and so on:
struct TrainCar {
// ...
Color color;
std::string registration_number;
unsigned long destination_id;
}
struct PowerCar : TrainCar {
// ...
const RealPowerCar &engine;
}
struct CargoCar : TrainCar {
// ...
const RealCargoCar &cargo;
bool full;
}
std::vector<TrainCar*> cars;
cars.push_back(new TrainCar(...));
cars.push_back(new TrainCar(...));
cars.push_back(new CargoCar(...));
cars.push_back(new CargoCar(...));
cars.push_back(new CargoCar(...));
An algorithm will iterate through the cars in the train, and decide how to route/shunt each car (whether to keep it in the train, move it to another point in the train, remove it from the train). This code looks like:
std::vector<TrainCar*>::iterator it = cars.begin();
for (; it != cars.end(); ++it) {
PowerCar *pc = dynamic_cast<PowerCar*>(*it);
CargoCar *cc = dynamic_cast<CargoCar*>(*it);
if (pc) {
// Apply some PowerCar routing specific logic here
if (start_of_train) {
// Add to some other data structure
}
else if (end_of_train && previous_car_is_also_a_powercar) {
// Add to some other data structure, remove from another one, check if something else...
}
else {
// ...
}
}
else if (cc) {
// Apply some CargoCar routing specific logic here
// Many business logic cases here
}
}
I am unsure whether this pattern (with the dynamic_casts, and chain of if statements) is the best way to process the list of simple structs of varying types. The use of dynamic_cast seems incorrect.
One option would be to move the routing logic to the structs (so like (*it)->route(is_start_of_car, &some_other_data_structure...)), however I'd like to keep the routing logic together if possible.
Is there a better way of iterating through different types of simple struct (with no methods)?, or do I keep the dynamic_cast approach?
The standard solution to this is called double-dispatch. Basically, you first wrap your algorithms in separate functions that are overloaded for each type of car:
void routeCar(PowerCar *);
void routeCar(CargoCar *);
Then, you add a route method to car that is pure virtual in the base-class, and implemented in each of the subclasses:
struct TrainCar {
// ...
Color color;
std::string registration_number;
unsigned long destination_id;
virtual void route() = 0;
}
struct PowerCar : TrainCar {
// ...
const RealPowerCar &engine;
virtual void route() {
routeCar(this);
}
}
struct CargoCar : TrainCar {
// ...
const RealCargoCar &cargo;
bool full;
virtual void route() {
routeCar(this);
}
}
Your loop then looks like this:
std::vector<TrainCar*>::iterator it = cars.begin();
for (; it != cars.end(); ++it) {
(*it)->route();
}
If you want to choose between different routing-algorithms at run-time, you can wrap the routeCar-functions in an abstract base class and provide different implementations for that. You would then pass the appropriate instance of that class to TrainCar::route.
If the number of classes is manageable, you can give a try to boost::variant.
Using "sum types" in C++ is sometimes a mess, so it is either this or double dispatching.
The classical OO solution would be to make all of the relevant functions
virtual in the base class TrainCar, and put the concrete logic in each
class. You say, however, that you'd like to keep the routing logic
together if possible. There are cases where this is justified, and the
classical solution in such cases is a variant union (boost::variant,
for example). It's up to you to decide which is better in your case.
Compromises are possible as well. For example, one can easily imagine a
case where the routing logic is somewhat independent of the car type
(and you don't want to duplicate it in each car type), but it does
depend on a certain number of characteristics of the car type. In this
case, the virtual function in TrainCar could simply return an object
with the necessary dependent information, to be used by the routing
algorithm. This solution has the advantage of reducing the coupling
between the routing and TrainCar to the minimum necessary.
Depending on the nature of this information, and how it is
used, the returned object could be polymorphic, with it's inheritance
hierarchy reflecting that of TrainCar; in this case, it must be
allocated dynamically, and managed: std::auto_ptr was designed with
exactly this idiom in mind.

Most effective method of executing functions an in unknown order

Let's say I have a large, between 50 and 200, pool of individual functions whose job it is to operate on a single object and modify it. The pool of functions is selectively put into a single array and arranged in an arbitrary order.
The functions themselves take no arguments outside of the values present within the object it is modifying, and in this way the object's behavior is determined only by which functions are executed and in what order.
A way I have tentatively used so far is this, which might explain better what my goal is:
class Behavior{
public:
virtual void act(Object * obj) = 0;
};
class SpecificBehavior : public Behavior{
// many classes like this exist
public:
void act(Object * obj){ /* do something specific with obj*/ };
};
class Object{
public:
std::list<Behavior*> behavior;
void behave(){
std::list<Behavior*>::iterator iter = behavior.front();
while(iter != behavior.end()){
iter->act(this);
++iter;
};
};
};
My Question is, what is the most efficient way in C++ of organizing such a pool of functions, in terms of performance and maintainability. This is for some A.I research I am doing, and this methodology is what most closely matches what I am trying to achieve.
edits: The array itself can be changed at any time by any other part of the code not listed here, but it's guaranteed to never change during the call to behave(). The array it is stored in needs to be able to change and expand to any size
If the behaviour functions have no state and only take one Object argument, then I'd go with a container of function objects:
#include <functional>
#include <vector>
typedef std::function<void(Object &)> BehaveFun;
typedef std::vector<BehaveFun> BehaviourCollection;
class Object {
BehaviourCollection b;
void behave() {
for (auto it = b.cbegin(); it != b.cend(); ++it) *it(*this);
}
};
Now you just need to load all your functions into the collection.
if the main thing you will be doing with this collection is iterating over it, you'll probably want to use a vector as dereferencing and incrementing your iterators will equate to simple pointer arithmetic.
If you want to use all your cores, and your operations do not share any state, you might want to have a look at a library like Intel's TBB (see the parallel_for example)
I'd keep it exactly as you have it.
Perofmance should be OK (there may be an extra indirection due to the vtable look up but that shouldn't matter.)
My reasons for keeping it as is are:
You might be able to lift common sub-behaviour into an intermediate class between Behaviour and your implementation classes. This is not as easy using function pointers.
struct AlsoWaveArmsBase : public Behaviour
{
void act( Object * obj )
{
start_waving_arms(obj); // Concrete call
do_other_action(obj); // Abstract call
end_waving_arms(obj); // Concrete call
}
void start_waving_arms(Object*obj);
void end_waving_arms(Object*obj);
virtual void do_other_actions(Object * obj)=0;
};
struct WaveAndWalk : public AlsoWaveArmsBase
{
void do_other_actions(Object * obj) { walk(obj); }
};
struct WaveAndDance : pubic AlsoWaveArmsBase
{
void do_other_actions(Object * obj) { walk(obj); }
}
You might want to use state in your behaviour
struct Count : public Behavior
{
Behaviour() : i(0) {}
int i;
void act(Object * obj)
{
count(obj,i);
++i;
}
}
You might want to add helper functions e.g. you might want to add a can_act like this:
void Object::behave(){
std::list<Behavior*>::iterator iter = behavior.front();
while(iter != behavior.end()){
if( iter->can_act(this) ){
iter->act(this);
}
++iter;
};
};
IMO, these flexibilities outweigh the benefits of moving to a pure function approach.
For maintainability, your current approach is the best (virtual functions). You might get a tiny little gain from using free function pointers, but I doubt it's measurable, and even if so, I don't think it is worth the trouble. The current OO approach is fast enough and maintainable. The little gain I'm talking about comes from the fact that you are dereferencing a pointer to an object and then (behind the scenes) dereferencing a pointer to a function (which happening as the implementation of calling a virtual function).
I wouldn't use std::function, because it's not very performant (though that might differ between implementations). See this and this. Function pointers are as fast as it gets when you need this kind of dynamism at runtime.
If you need to improve the performance, I suggest to look into improving the algorithm, not this implementation.