I am working on an application that parses user input (command) and tries to process the command. There are various types of command. So I created one Base class, which all commands will inherit from. Now I am trying to figure out how to correctly process the command. What I would like to do is to create an instance of the Base class and then somehow recast it to the correct descendant. Ideally, this would be done at the level of the command classes, eg Base, Der1, Der2, no in main function as in example.
main.cpp
#include "class1.hpp"
int main(int argc, const char * argv[]) {
Base com("some input");
com.process(); //based on the input I want to distinguish which of the derived classes should be used
}
class1.hpp
#include <iostream>
class Base {
std::string input;
public:
Base(std::string input) {
this->input = input;
}
virtual void process(){}
};
class Der1 {
public:
Der1(std::string input);
void process() {
std::cout << "Der1 process" << std::endl;
}
};
class Der2 {
public:
Der2(std::string input);
void process() {
std::cout << "Der2 process" << std::endl;
}
};
Is this correct attitude when parsing user input? Or maybe is there some different approach that I might try? I prefer to use polymorphism as part of learning c++.
Thank you for any answer.
Is this correct attitude when parsing user input?
In C++, we usually try to keep the full type instead of erasing it to a base class: then we need no virtual dispatch, can fully use templates/overloads etc.
Or maybe is there some different approach that I might try?
Definitely: try to use static polymorphism instead. I think in your example something like this would be enough:
struct Der1 {
Der1(std::string_view); // TODO
auto process() { return "processed by Der1"sv; }
};
struct Der2 {
Der2(std::string_view); // TODO
auto process() { return "processed by Der2"sv; }
};
auto process(std::string_view input) {
switch (input.at(0)) { // I don't know how you actually want to choose DerN
case '1': return Der1{input}.process();
case '2': return Der2{input}.process();
default: throw std::runtime_error{"couldn't decide how to process"};
}
}
int main() { std::cout << process("1some input") << '\n'; }
Related
Knowing that this might be an inappropriate question (since the reply can be (will be) based only on personal, subjective opinions) I still risk asking it:
We wrote some code and came up with the following construct
#include <iostream>
#include <string>
class Generic
{
public: virtual void do_work() = 0;
};
class SomeAppDescriptor : public Generic
{
public: static std::string name() { return "SomeAppDescriptor"; }
};
template <class TGenericApp>
class CommonFunctionalities : public TGenericApp
{
public: void do_common_work() {
std::cout << "do_common_work for " << TGenericApp::name();
}
};
class RealClass : public CommonFunctionalities<SomeAppDescriptor>
{
public: virtual void do_work() {
do_common_work();
std::cout << "and doing the work" << std::endl;
}
};
int main(int argc, char const *argv[])
{
RealClass a;
a.do_work();
return 0;
}
And now we are in the documentation phase ... We need to come up with a name for the construct where CommonFunctionalities inherits from the template member ... and is using the properties of the SomeAppDescriptor which is actually the template member... If you are to name this construct, what would be an appropriate name for it?
Edit
The main idea is that there are a lot of AppDescriptor classes which read some data from configuration files (name, ip, database, etc ...), and there is a middle layer (here it is represented by CommonFunctionalities which does the work (but also at some obscure point the CommonFunctionalities objects are mapped to name() (map of string and Generic) in order to get the functionality of the do_work()), and at the end someone from somewhere is calling the do_work of a Generic which is implemented in a set of "upper" layer classes (RealClass)
This looks, to me, like a botched attempt at a Decorator.
SomeAppDescriptor and CommonFunctionalities do not override do_work, so they need not inherit from Generic; however the use of do_common_work suggests that might have been useful.
if RealClass inherits from Generic directly, then it can take CommonFunctionalities by composition.
Using the Decorator pattern, I would end up with:
class Generic { public: virtual void do_work() = 0; };
template <typename App>
class CommonFunctionalities: public Generic {
public:
virtual void do_work() override {
std::cout << "CommonFunctionalities - " << App::name() << "\n";
}
};
class RealClass: public Generic {
public:
RealClass(std::unique_ptr<Generic> p): previous(std::move(p)) {}
virtual void do_work() override {
if (previous) { previous->do_work(); }
std::cout << "RealClass\n";
}
private:
std::unique_ptr<Generic> previous;
};
int main() {
RealClass rc{std::make_unique< CommonFunctionalities<SomeAppDescriptor> >()};
Generic& g = rc;
g.do_work();
return 0;
}
The Decorator was specifically created to layer the work, without any class knowing more than the interface class so that you can at runtime choose which layers to use. Even if the runtime flexibility is not necessary, it can still be advantageous to use this approach because it reduces the dependencies: RealClass knows not of CommonFunctionalities.
Note: in C++, you can also use the Decorator approach without interfaces thanks to templates.
It's the Curiously Recurring Template Pattern.
I think it's somewhat of an upgrade to the Curiously Recurring Template Pattern.
looks nice. :)
I need help getting the broken part of this code working.
How do I tag dispatch two functions (that return different value-types) based on a string?
If the overall code can be simplified with the intent of dispatching with strings, please do make recommendations. TY.
Requirements:
Dispatch based on a string
Rectangle overload needs to return int, while Circle overload needs to return std::string
The mapping from Rectangle_Type to int and Circle_Type to std::string is fixed and known at compile time. Part of my problem is std::map is a run-time construct: I don't know how to make the std::string to tag mapping a compile-time construct.
If necessary, run-time resolution is okay: however, the dispatch must allow for different return types based on the enum/type resolved to.
CODE
#include <map>
#include <string>
#include <iostream>
struct Shape { };
struct Rectangle_Type : public Shape { using value_type=int; };
struct Circle_Type : public Shape { using value_type=std::string; };
Rectangle_Type Rectangle;
Circle_Type Circle;
static std::map<std::string,Shape*> g_mapping =
{
{ "Rectangle", &Rectangle },
{ "Circle", &Circle }
};
int tag_dispatch( Rectangle_Type )
{
return 42;
}
std::string tag_dispatch( Circle_Type )
{
return "foo";
}
int
main()
{
std::cerr << tag_dispatch( Circle ) << std::endl; // OK
std::cerr << tag_dispatch( Rectangle ) << std::endl; // OK
#define BROKEN
#ifdef BROKEN
std::cerr << tag_dispatch( (*g_mapping["Rectangle"]) ) << std::endl;
std::cerr << tag_dispatch( (*g_mapping["Circle"]) ) << std::endl;
#endif
}
Unless C++11 has changed this.. The problem is that you are dereferencing a Shape* pointer, which means the resulting datatype (Shape&) does not have a valid overload of tag_dispatch.
You can do something like g_mapping["Rectangle"]->tag_dispatch(). Or more cleanly rewrite as below.
std::string tag_dispatch( Shape& shape)
{
return shape->tag_dispatch();
}
This way you can support non Shape objects with an identical interface. Both need you to make tag_dispatch as a virtual function of Shape as well.
C++ does not have dynamic dispatch. This is probably what you expect to happen. You can emulate it with dynamic_cast, but that's slow and not recommended. You could use a virtual function returning an enum for the type though.
class base
{
public:
virtual ~base() // Don't forget the virtual destructor if you want to inherit from it!
{}
enum type
{
a,
b,
};
virtual type get_type() const = 0;
};
class a : public base
{
public:
virtual type get_type()
{
return base::type::a;
}
};
class b : public base
{
public:
virtual type get_type()
{
return base::type::b;
}
};
I'm trying to make a sanely-usable implementation of my events system. In order to identify event types,
I have what I call a "type path,' which identifies the path to an event type through the hierarchy.
This way, I can handle, for example, all InputEvents at one place whether they're key presses, mouse input,
or whatever else. A sticky issue, though, has been giving event types their identities. What I've most
recently done is do this by having each instance retrieve a leaf identity from a static member function
of the Event class, which serves simply as an interface other than performing this function.
However, the simplest way to ensure that each type has exactly one identity within this structure
seemed to be to use maps based on type paths (up to but excluding the leaf identity/identifier)
and typeid().hash_code().
Specifically, what I want to have is a system to which events can be added easily without
having to look up a bunch of information or perform a lot of silly boilerplate crap. Considering this
(and possibly things I'm not realizing I should want?),
Is this design flawed in any obvious ways?
Is there a Betterâ„¢ way than to use typeid()? I've read a bit about it and it seems to be considered something that, depending on the person whose opinion is being asked, should either never be used or be used almost never. As it's possible that I'm just rusty or being stupid, I'd like to know if anyone knows of a solution that is, if nothing else, less uncertain (apparently some implementations of typeid() are pretty bad, though I don't know which or if it's bad enough to seriously matter).
Fairly simple example of what I have now:
#include <iostream>
#include <vector>
#include <typeinfo>
#include <map>
void spew(std::vector<unsigned int> vect) { for (unsigned int i=0;i<vect.size();++i) std::cout << vect.at(i) << ","; std::cout << std::endl; }
class Foo
{
public:
Foo() {}
virtual ~Foo() {}
static unsigned int getSubtype(std::vector<unsigned int> typePath, Foo *evt)
{
static std::map<std::vector<unsigned int>, std::map<std::size_t, unsigned int> > typeMap;
std::size_t typehash = typeid(*evt).hash_code();
if (typeMap.find(typePath) == typeMap.end())
{
unsigned int val = typeMap[typePath].size();
typeMap[typePath][typehash] = val;
return val;
}
else
{
if (typeMap[typePath].find(typehash) == typeMap[typePath].end())
{
unsigned int val = typeMap[typePath].size();
typeMap[typePath][typehash] = val;
return val;
}
return typeMap[typePath][typehash];
}
}
virtual void test() { std::cout << "Foo" << std::endl; }
protected:
std::vector<unsigned int> m_typePath;
};
class Bar : public Foo
{
public:
Bar()
{
m_typePath.push_back(Foo::getSubtype(m_typePath, this));
test();
}
virtual ~Bar() {}
virtual void test() { std::cout << "Bar: "; spew(m_typePath);}
};
class Baz : public Foo
{
public:
Baz()
{
m_typePath.push_back(Foo::getSubtype(m_typePath, this));
test();
}
virtual ~Baz() {}
virtual void test() { std::cout << "Baz: "; spew(m_typePath);}
};
class Qux : public Baz
{
public:
Qux()
{
m_typePath.push_back(Foo::getSubtype(m_typePath, this));
test();
}
virtual ~Qux() {}
virtual void test() { std::cout << "Qux: "; spew(m_typePath);}
};
int main()
{
Foo foo0;
std::cout << "----" << std::endl;
Bar bar0;
std::cout << "----" << std::endl;
Baz baz0;
std::cout << "----" << std::endl;
Qux qux0;
}
Output:
----
Bar: 0,
----
Baz: 1,
----
Baz: 1,
Qux: 1,0,
This and other tests exhibit the desired behavior, to be clear.
Edit: Previous title didn't really match what I mean to ask.
Possibly relevant notes: This is meant for part of a library, and a highly parallel one at that. I've omitted code relevant to concurrency for simplicity of representing the design, but it may be that such information would be useful for design purposes as well. Also note that I'm still only asking for help with creating/assigning type identifiers; I mention these because some designs may not be applicable given their implied constraints.
Win edit:
Well, I have an implementation that's ridiculously fast and does exactly what I need. With a few derived classes, I can instantiate ten million per ~thread(I added in TBB for some other tests; it may or may not use exactly eight threads however it pleases) spread across the derived classes, each having two or more elements in its path, in typically well under .02s. Original implementation managed about four or five seconds depending on containers and such and was just silly. Result (enough to get the idea, anyway):
template<typename T> class EventID
{
public:
static const std::size_t typeID;
};
template<typename T> const std::size_t EventID<T>::typeID = typeid(T).hash_code();
class Foo
{
public:
Foo()
{
m_typePath.push_back(EventID<Foo>::typeID);
}
protected:
neolib::vecarray<std::size_t, 100, neolib::nocheck> m_typePath;
};
class Bar : public Foo
{
public:
Bar()
{
m_typePath.push_back(EventID<Bar>::typeID);
}
};
I would rely on the class hierarchy that the compiler maintains, plus a list of type codes:
typedef enum { EVENT, INPUT, MOUSE, MOUSEDOWN, MOUSEUP, MOUSEMOVE, KEYBOARD, KEYDOWN, KEYUP } EventType;
typedef std::vector<EventType> ETVector;
class Event
{
public:
virtual void appendType(ETVector& v) { v.push_back(EVENT); }
};
class InputEvent : public Event
{
public:
virtual void appendType(ETVector& v) { v.push_back(INPUT); Event::appendType(v); }
};
class MouseEvent : public InputEvent
{
public:
virtual void appendType(ETVector& v) { v.push_back(MOUSE); InputEvent::appendType(v); }
};
class MouseDownEvent : public MouseEvent
{
public:
virtual void appendType(ETVector& v) { v.push_back(MOUSEDOWN); MouseEvent::appendType(v); }
};
class MouseUpEvent : public MouseEvent
{
public:
virtual void appendType(ETVector& v) { v.push_back(MOUSEUP); MouseEvent::appendType(v); }
};
class MouseMoveEvent : public MouseEvent
// . . .
class KeyboardEvent : public InputEvent
// . . .
class KeyDownEvent : public KeyboardEvent
// . . .
class KeyUpEvent : public KeyboardEvent
// . . .
Then to do your test, you would have something like this:
KeyUpEvent kue;
EventTypeVector type_path;
kue.appendType(type_path);
for (EventTypeVector::const_iterator i = type_path.begin(); i != type_path.end(); i++)
{
cout << *i << endl;
}
The vector stores your type path. There is no runtime storage cost, and no static variables. It might be possible to use typeid instead of a manually maintained enum, but with an enum everything is under your control, and you can easily avoid conflicts with other types in your program. Alternatively, it might be possible to imbue a class with the appendType() method by means of a template, to reduce the code even further.
It is a little tedious to have to explicitly name the parent class in appendType(), but I know of no other way in C++, thanks to multiple inheritance. In Java I could have used super, though reflection would probably be a better approach.
Is this simpler than what you have, or am I missing something? Good luck.
See final edit to original post for solution.
This is probably a basic question for a regular C++ user. Functionally, I have an ECG monitor, and want to choose which output format to use at runtime. I have set up two classes that expose the same methods and members (ECGRecordingDefaultFormat and ECGRecordingEDFFormat) eg. ->InsertMeasure, ->setFrequency, ->setPatientName etc.
I know I could define one instance of each format class type, then put in:
if (ECGFormatToUse == ECGFormat.EDF) {
ecgDefaultFormat.InsertMeasure(x);
}
if (ECGFormatToUse == ECGFormat.Default) {
ecgEDFFormat.InsertMeasure(x);
}
all throughout the code, but I think I might not be using C++'s dynamic typing to its full extent.
The question is: can I define just one variable in main(), and after choosing the format I want at runtime, have the code use the right class with its exposed 'InsertMeasure' method, avoiding a whole lot of if/else's throughout the code?
I'd be happy with just a reference to which aspect of inheritance/polymorphism (?) I should be using, and can google away the rest.
Thanks guys.
Pete
You can combine the factory pattern with C++'s polymorphism.
class Base
{
virtual void InsertMeasure() = 0; //virtual pure, make the base class abstract
};
class ECGRecordingDefaultFormat : public Base
{
virtual void InsertMeasure();
};
class ECGRecordingEDFFormat : public Base
{
virtual void InsertMeasure();
};
class Factory
{
static Base* create(ECGFormat format)
{
if ( format == ECGFormat.EDF )
return new ECGRecordingEDFFormat;
if ( format == ECGFormat.Default )
return new ECGRecordingDefaultFormat;
return NULL;
}
};
int main()
{
ECGFormat format;
//set the format
Base* ECGRecordingInstance = Factory::create(format);
ECGRecordingInstance->InsertMeasure();
return 0;
}
Others have already answered but I posted this as I had it written:
class EcgFormat
{
public:
virtual void InsertMeasure(int x) = 0;
};
class EcgFormatA : public EcgFormat
{
public:
void InsertMeasure(int x)
{
cout << "EcgFormatA: " << x << "\n";
}
};
class EcgFormatB : public EcgFormat
{
public:
void InsertMeasure(int x)
{
cout << "EcgFormatB: " << x << "\n";
}
};
class EcgFormatFactory
{
public:
static std::shared_ptr<EcgFormat> makeEcgFormat(char a_format)
{
switch (a_format)
{
case 'A':
return std::make_shared<EcgFormatA>();
break;
case 'B':
return std::make_shared<EcgFormatB>();
break;
default:
throw std::exception("Invalid format");
break;
}
}
};
int main()
{
std::shared_ptr<EcgFormat> format = EcgFormatFactory::makeEcgFormat('A');
format->InsertMeasure(5);
return 0;
}
(I know this pretty much the same as #Luchian answer).
Have an abstract super class EcgFormat (with several virtual methods kept abstract with =0) and several sub-classes ECGRecordingDefaultFormat, ECGRecordingEDFFormat etc
I need several C++ classes to have a static method "register", however the implementation of register varies between those classes.
It should be static because my idea is to "register" all those classes with Lua (only once of course).
Obviously I can't declare an interface with a static pure virtual function. What do you guys suggest me to do ? Simplicity is welcome, but I think some kind of template could work.
Example of what I would like to achieve
class registerInterface
{
public:
static virtual void register() = 0; //obviously illegal
};
class someClass: public registerInterface
{
static virtual void register()
{
//I register myself with Lua
}
}
class someOtherClass: public registerInterface
{
static virtual void register()
{
//I register myself with Lua in a different way
}
}
int main()
{
someClass::register();
someOtherClass::register();
return 0;
}
Based on how you've described the problem, it's unclear to me why you even need the 'virtual static method' on the classes. This should be perfectly legal.
class SomeClass {
static void register(void) {
...
}
}
class SomeOtherClass {
static void register(void) {
...
}
}
int main(int argc, char* argv[]) {
SomeClass::register();
SomeOtherClass::register();
return 0;
}
Drop the RegisterInterface, I don't think you need it.
If it helps, you could take Hitesh's answer, and add:
struct luaRegisterManager {
template <typename T>
void registrate() {
T::registrate();
// do something else to record the fact that we've registered -
// perhaps "registrate" should be returning some object to help with that
}
};
Then:
int main() {
luaRegisterManager lrm;
lrm.registrate<someClass>();
lrm.registrate<someOtherClass>();
}
More generally, if you want to introduce any dynamic polymorphism in C++, then you need an object, not just a class. So again, perhaps the various register functions should be returning objects, with some common interface base class registeredClass, or classRegistrationInfo, or something along those lines.
Could provide an example of what you feel it is that you need dynamic polymorphism for? Hitesh's code precisely matches your one example, as far as I can see, so that example must not cover all of your anticipated use cases. If you write the code that would be using it, perhaps it will become clear to you how to implement it, or perhaps someone can advise.
Something else that might help:
#include <iostream>
#include <string>
#include <vector>
struct Registered {
virtual std::string name() = 0;
virtual ~Registered() {}
Registered() {
all.push_back(this);
}
static std::vector<Registered*> all;
};
std::vector<Registered*> Registered::all;
typedef std::vector<Registered*>::iterator Iter;
template <typename T>
struct RegisteredT : Registered {
std::string n;
RegisteredT(const std::string &name) : n(name) { T::registrate(); }
std::string name() { return n; }
// other functions here could be implemented in terms of calls to static
// functions of T.
};
struct someClass {
static Registered *r;
static void registrate() { std::cout << "registering someClass\n"; }
};
Registered *someClass::r = new RegisteredT<someClass>("someClass");
struct someOtherClass {
static Registered *r;
static void registrate() { std::cout << "registering someOtherClass\n"; }
};
Registered *someOtherClass::r = new RegisteredT<someOtherClass>("someOtherClass");
int main() {
for (Iter it = Registered::all.begin(); it < Registered::all.end(); ++it) {
std::cout << (*it)->name() << "\n";
}
}
There are all sorts of problems with this code if you try to split it across multiple compilation units. Furthermore, this kind of thing leads to spurious reports from memory leak detectors unless you also write some code to tear everything down at the end, or use a vector of shared_ptr, Boost pointer vector, etc. But you see the general idea that a class can "register itself", and that you need an object to make virtual calls.
In C++ you usually try to avoid static initialisation, though, in favour of some sort of setup / dependency injection at the start of your program. So normally you would just list all the classes you care about (calling a function on each one) rather than try to do this automatically.
Your intentions are noble, but your solution is inkling towards "overengineering" (unless I am missing an obvious solution).
Here is one possibility: You can use the Virtual Friend function idiom For example,
class RegisterInterface{
friend void register(RegisterInterface* x){x->do_real_register();}
protected:
virtual void do_real_register();
}
class Foo : public RegisterInterface{
protected:
virtual void do_real_register(){}
};
class Bar : public RegisterInterface{
protected:
virtual void do_real_register(){}
};
int main(int argc, char* argv[]) {
BOOST_FOREACH(RegisterInterface* ri, registered_interfaces)
{
register(ri);
}
return 0;
}
I know you've already accepted an answer, but I figured I would write this up anyway. You can have self-registering classes if you use some static initialization and the CRTP:
#include <vector>
#include <iostream>
using namespace std;
class RegisterableRoot // Holds the list of functions to call, doesn't actually need
// need to be a class, could just be a collection of globals
{
public:
typedef void (*registration_func)();
protected:
static std::vector<registration_func> s_registery;
public:
static void do_registration()
{
for(int i = 0; i < s_registery.size(); ++i)
s_registery[i]();
}
static bool add_func(registration_func func) // returns something so we can use it in
// in an initializer
{
s_registery.push_back(func);
return true;
}
};
template<typename RegisterableType> // Doesn't really need to inherit from
class Registerable : public RegisterableRoot // RegisterableRoot
{
protected:
static const bool s_effect;
};
class A : public Registerable<A> // Honestly, neither does A need to inherit from
// Registerable<T>
{
public:
static void Register()
{
cout << "A" << endl;
}
};
class B : public Registerable<B>
{
public:
static void Register()
{
cout << "B" << endl;
}
};
int main()
{
RegisterableRoot::do_registration();
return 0;
}
std::vector<RegisterableRoot::registration_func> RegisterableRoot::s_registery;
template <typename RegisterableType> // This is the "cute" part, we initialize the
// static s_effect so we build the list "magically"
const bool Registerable<RegisterableType>::s_effect = add_func(&RegisterableType::Register);
template class Registerable<A>; // Explicitly instantiate the template
// causes the equivalent of
// s_registery.push_back(&A::Register) to
// be executed
template class Registerable<B>;
This outputs
A
B
although I wouldn't rely on this order if I were you. Note that the template class Registerable<X> need not be in the same translation unit as the call to do_registration, you can put it with the rest of your definition of Foo. If you inherit from Registerable<> and you don't write a static void Register() function for your class you'll get a (admittedly probably cryptic) compiler error much like you might expect if there really was such a thing as "static virtuals". The "magic" merely adds the class specific function to the list to be called, this avoids several of the pitfalls of doing the actual registration in a static initializer. You still have to call do_registration for anything to happen.
How about this way? Define an interface class:
// IFoobar.h
class IFoobar{
public:
virtual void Register(void) = 0;
}
Then define the class that handles the register..
// RegisterFoobar.h
class RegisterFoobar{
public:
// Constructors etc...
IFoobar* fooBar;
static void RegisterFoobar(IFoobar& fubar){
foobar = &fubar;
}
private:
void Raise(void){ foobar->Register(); }
}
Now, then define another class like this
// MyFuBar.h
class MyFuBar : IFoobar{
public:
// Constructors etc...
void Register(void);
private:
RegisterFoobar* _regFoobar;
}
Call the code like this:
//MyFuBar.cpp
MyFuBar::MyFuBar(){
_regFoobar = new Foobar();
_regFoobar->RegisterFoobar(this);
}
void MyFuBar::Register(void){
// Raised here...
}
Maybe I have misunderstood your requirements...