I'm trying to make platform independent code so I'm using OOP. For example, on Windows, Mac OS X, and Linux you can have windows, but on android you have views so I'm trying to abstract this.
I first made a class to represent a window or a view which I called view:
class View
{
public:
virtual ~View()
{}
virtual void display() = 0;
virtual void hide() = 0;
};
Now the problem is that on Android, there is no title for views while on Windows there are so I decided to create another class:
class NameableView : public View
{
public:
virtual void setName(const std::string& name)
};
And then finally implement the classes:
class WindowsView : public NameableView
{
/* Windows implementation */
}
class AndroidView : public View
{
/* Android implementation */
}
Then I need to make some code which sets the name for a view only if it is possible (if it inherits from the NameableView class).
So how can I solve this problem? I first thought about dynamic_cast but I often hear that having too much dynamic_cast is an indication of a design problem. I'm a beginner in C++ so maybe I didn't think the right way and I should change the whole design.
I'm trying to make platform independent code so I'm using OOP.
This is not an optimal approach - polymorphic hierarchies and virtual functions allow different concrete object types that inherit from the same interface to behave differently at run-time, but you know the platform you're going to target at compile-time.
What you should instead do is use static polymorphism and CRTP to provide a common interface that every concrete per-platform implementation must satisfy.
template <typename TDerived>
struct View
{
void display() { static_cast<TDerived&>(*this).display(); }
void hide() { static_cast<TDerived&>(*this).hide(); }
constexpr bool supportsSetView() const
{
return static_cast<TDerived&>(*this).supportsSetView();
}
};
In the case of setName, you should provide a supportsSetView check on every platform that returns true at compile-time if the view can be named. Then you perform that check on the caller side and only invoke setName if the check passes.
Example usage:
#if defined(PLATFORM_ANDROID)
struct AndroidView
{
// ...
constexpr bool supportsSetView() const { return false; }
};
using MyView = View<AndroidView>;
#else if defined(PLATFORM_WINDOWS)
struct WindowsView
{
// ...
constexpr bool supportsSetView() const { return true; }
void setName(std::string x) { /* ... */ }
};
using MyView = View<WindowsView>;
#else
#error "Unsupported platform."
#endif
Caller side:
MyView currentView;
if constexpr(currentView.supportsSetView())
{
currentView.setName("something");
}
As if constexpr(...)'s evaluation occurs at compile-time, the code will only call setName if it is supported by MyView.
Related
I have many interfaces for different listeners, the all look like this:
class ListenerA
{
public:
virtual void
onEventA(const EventA&) = 0;
};
class ListenerB
{
public:
virtual void
onEventB(const EventB&) = 0;
};
When testing, I always end up just collecting those events in a std::vector for analyzing them afterwards in a specific test suite. Those event collectors all look the same like this one for example:
class EventACollector : public ListenerA
{
public:
const auto&
events() const
{
return m_events;
}
private:
void
onEventA(const EventA& event) override
{
m_events.emplace_back(event);
}
std::vector<EventA> m_events;
};
Is there a way to template an EventTCollector, so that I do not have to write it every time? Given that the virtual function name does change for every listeners?
C++ does not have introspection, so you cannot find the virtual function in ListenerA. The other parts can go in a templated base class, but the override you'll need to define manually.
Modern C++ would use a std::function<void(EventA)> instead of a named interface, but that won't help you as a user of that old interface.
I have a diagnostic drawing class to graphically plot the status of objects in a multithreaded environment. But this is costing me CPU cycles when I don't run in the diagnostic mode. I don't want to check every line for diagnose mode too. Rather I like to a declare the diagnostic object as empty ( or through some other member functions/ extra variables) and all the diagnostic member functions will be rendered irrelevant. Is this possible? I dont't want to change the existing member functions
bool dmode = true; // want to avoid this
class plot{
void draw();
};
class foo{
void something(){
plot p;
if(dmode) p.draw(); // don't want the checking as plot objects are littered everywhere.
}
};
Edited:
// dmode will be decided only at run time based on my settings configuration
Compile time discard
You may use constexpr:
constexpr bool dmode = true;
//...
if constexpr (dmode) {
Using constexpr this way will make sure the branch is discarded at compile time
It should be noted that this is a c++17 feature, before that you can use macros to discard code at compile time.
A third option is to just rely on compiler optimizations(ie. constant folding), but it is much harder to give any guarentees and might not be feasible for a debug build if that is ever the case.
Runtime solution
Assuming your draw function is virtual - you then need to somehow make a non-virtual function to stick the if into. Then one way to accomplish this is by making the virtual function private.
class plot{
public:
void draw() {
if (!dmode) {
return;
}
do_draw();
}
private://<-- or protected
virtual void do_draw() = 0;//rename in all subclasses
};
However, this is just one way to solve it - without knowing more of the actual case its hard to say which method is more appropriate.
You can do the check inside the draw() function:
void plot::draw() {
if (!dmode) {
return;
}
// Do the actual drawing.
}
If that's not an option for some reason, you could make plot a pure abstract class, and provide two implementations, RealPlot and NullPlot. Then create a function create_plot() that, depending on the value of dmode, returns either a RealPlot or a NullPlot instance.
You have options. Here are some of them:
Concepts - C++20
constexpr bool dmode = true;
class plot
{
public:
void draw() requires (!dmode)
{
/* actual implementation */
}
void draw() requires dmode
{
// empty
}
};
class foo
{
void something()
{
plot p;
p.draw();
}
};
Constexpr if - C++17
constexpr bool dmode = true;
class plot
{
public:
void draw()
{
if constexpr (!dmode)
{
/* actual implementation */
}
}
};
class foo
{
void something()
{
plot p;
p.draw();
}
};
Templated class and an alias - C++11
constexpr bool dmode = true;
template <bool Dmode>
class plot_base
{
public:
void draw()
{
/* actual implementation */
}
};
template <>
class plot_base<true>
{
public:
void draw()
{
// empty
}
};
template <bool Dmode = dmode>
using plot = plot_base<Dmode>;
class foo
{
void something()
{
plot<> p;
p.draw();
}
};
Mock (a.k.a. None of the above)
And ultimately (most likely) none of the solutions are appropriate. It seems to me like what you want is a mock. So look into that.
There's a hierarchy of classes describing different properties of some object. The abstract class Property is a base class, and it has children: IntegerProperty, BooleanProperty, and so on. All data is encoded in QString and derived classes decode it in their own way.
class Property : public QObject
{
Q_OBJECT
public:
// ...
virtual QString value() const = 0;
virtual bool setValue(const QString &value) = 0;
virtual bool validateValue(const QString& value) = 0;
// ...
};
class IntegerProperty : public Property
{
// ...
virtual QString value() const override;
virtual bool setValue(const QString &value) override;
virtual bool validateValue(const QString& value) override;
// ...
};
// ...
Every property class must have an independent editor (GUI widget) - PropertyEditor (abstract class again), IntegerPropertyEditor, BooleanPropertyEditor, and so on.
class PropertyEditor : public QWidget
{
Q_OBJECT
public:
inline Facer::PropertyPointer attachedProperty() { return m_property; }
protected:
PropertyEditor(Facer::PropertyPointer attachedProperty, QWidget* parent = nullptr);
virtual void mousePressEvent(QMouseEvent* event) override;
virtual bool eventFilter(QObject *watched, QEvent *event) override;
// ...
};
class IntegerPropertyEditor : public PropertyEditor
{
// ...
};
// ...
For example, I have a set of different properties. I don't know which exactly properties I have because they are all pointers to Property class. My task is to create specified editors of these properties, so I need to get IntegerPropertyEditor if the property object is IntegerProperty.
for (Property* property : propertySet())
PropertyEditor* editor = createEditor(property);
I made a temporary workaround with macro:
#define IF_TYPE_GET_EDITOR(propertyType, editorType) \
if (std::dynamic_pointer_cast<propertyType>(property)) \
return new editorType(property, this);
// ...
PropertyEditor *PropertySetWidget::create(PropertyPointer property)
{
IF_TYPE_GET_EDITOR(BooleanProperty, BooleanPropertyEditor)
else IF_TYPE_GET_EDITOR(ColorProperty, ColorPropertyEditor)
else IF_TYPE_GET_EDITOR(FloatingPointProperty, FloatingPointPropertyEditor)
else IF_TYPE_GET_EDITOR(FontProperty, FontPropertyEditor)
else IF_TYPE_GET_EDITOR(IntegerProperty, IntegerPropertyEditor)
else IF_TYPE_GET_EDITOR(TextProperty, TextPropertyEditor)
else throw std::runtime_error("This PropertyType is not implemented yet");
}
It doesn't look like a good solution - if I add a new type of property and its editor, I'll have to update this code as well. What is the most convenient and generic way to link an editor class and a property class?
This might give some extra code, especially depending on how your project is set up, but one solution is to make a virtual function in Property that returns a pointer to an editor:
class Property : public QObject
{
public:
virtual PropertyEditor* CreateEditor(PropertySetWidget* widget) {
// let's put our default behavior here
throw std::runtime_error("This PropertyType is not implemented yet");
}
//...
};
Now, you make each class responsible for supplying its own editor:
class IntegerProperty : public Property
{
public:
// doesn't have to be virtual, I don't think Just a regular version should be fine too.
virtual PropertyEditor* CreateEditor(PropertySetWidget* widget) {
return new IntegerPropertyEditor(this, widget);
}
//...
};
Depending on how many classes you have, that may be a lot of copying and pasting.
However, the fun part is PropertySetWidget::create():
PropertyEditor *PropertySetWidget::create(PropertyPointer property)
{
return property->CreateEditor(this);
}
Because every child of property is responsible for supplying its own editor, we don't have to worry about it at this level. If one doesn't exist/isn't implemented, property::CreateEditor() will throw an error for you. If one does exist/is implemented, it will return a pointer to a new instance the editor automatically.
The big advantage is that if you add a new property and its editor, you don't have to touch it this function at all. The virtual function takes care of properly implementing it for you. If the new property has an editor, it just needs to overload that function, and this create() still works properly.
Of course, you will have to modify Property's interface this way, which may not be feasible in your case. That's the major drawback to this approach.
What you want requires Reflection implemented, although there are rather cumbersome and ugly ways to implement what you wanted without macros. I personally recommend the solution of #Chipster.
If you are still interested in methods that do not require Property to provide its own editor... I wrote an example, you can check it out.
#include <iostream>
#include <memory>
class A
{ //virtual working class
public:
virtual ~A() = default;
};
//two possible implementations
class B : public A {};
class C : public A {};
//Editor interface
class EditorA
{
public:
virtual ~EditorA() = default;
virtual void print() = 0;
};
//Implementations of editors
class EditorB :
public EditorA
{
public:
void print() override
{
std::cout << "Editor B\n";
}
};
class EditorC :
public EditorA
{
public:
void print() override
{
std::cout << "Editor C\n";
}
};
//template class used for declaring which Editor you use depending on the class you provide
// I would make a namespace but there are no template namespaces
template<typename T>
class EditorT;
template<>
class EditorT<B>
{
public:
using EditorType = EditorB;
};
template<>
class EditorT<C>
{
public:
using EditorType = EditorC;
};
using namespace std;
// Recursive GetEditor code... written inside class as a static method for reasons.
template<typename... Args>
class CEditorIdentifier;
template<>
class CEditorIdentifier<>
{
public:
static EditorA * GetEditor(shared_ptr<A>& val)
{
return nullptr;
}
};
template<typename Arg, typename... Args>
class CEditorIdentifier<Arg, Args...>
{
public:
static EditorA * GetEditor(shared_ptr<A>& val)
{
if(std::dynamic_pointer_cast<Arg>(val))
{
return new typename EditorT<Arg>::EditorType;
}
return CEditorIdentifier<Args...>::GetEditor(val);
}
};
template<typename... Args>
EditorA* FindEditor(shared_ptr<A>& val)
{
return CEditorIdentifier<Args...>::GetEditor(val);
}
int main()
{
shared_ptr<A> b = make_shared<B>();
shared_ptr<A> c = make_shared<C>();
EditorA* eB = FindEditor<B,C>(b);
EditorA* eC = FindEditor<C,B>(c);
eB->print();
eC->print();
return 0;
}
Now you can add additional classes D,E,F... you only have to maintain the reference classes EditorT<D>, EditorT<E>, EditorT<F>...
Complicated right? Well... current features in C++ for such programming are limited. It's being worked and will be available in the future (see Reflection TS) but not now. Also it will be simpler to implement in C++20 with all the extensions to constexpr.
I like the answer above about each Property having a virtual method to return the appropriate type of editor. The only downside to that is that it may tie user interface-related elements into your lower-level code. Depending on your needs, that may or may not be OK.
A variation of your original factory that keeps the editor creation separate from the property class definitions is that you could add a "propertyType" virtual method that returns an integer, and then your factory becomes a switch statement:
switch (Property.propertyType ())
{
case BooleanPropertyType: create Boolean property editor
case StringPropertyType: create String properly editor
etc.
}
You would have an enum somewhere with the defined property type values. It's the same basic idea, but it avoids the overhead of the dynamic cast. (Whether or not it's actually faster is something to test.)
I don't think there's anything fundamentally wrong with your approach other than the possible dynamic_cast overhead, and often, I think that having a factory method where all of the editors are created for all of the types can be easier to maintain than creating the UI elements in classes where you're trying to manage data. Purists may see this as a violation of good object oriented classes, but it really depends on your needs and who you're trying to please.
I like the concept of type traits, because it solves some design questions in a clear and extensible way. For example, imagine we have a couple of printer classes and document classes.
Since new document types may be added later, the printer should not directly know which document it is printing, so that it doesn't have to be adjusted then. On the other hand, documents shouldn't know about all printers.
By providing traits about how to print documents, this is the only place that must be modified when adding new documents. Moreover, if there are new printers, they can use the same traits directly and focus on the internal printing process that differs from the other printers.
// Documents
class pdf { /* ... */ };
class txt { /* ... */ };
// Traits
template<typename t>
struct traits; // No default trait, so new documents throw compilation error
template<>
struct traits<pdf> {
static std::string get_title(pdf& document) { /* ... */ }
static std::string get_content(pdf& document) { /* ... */ }
static bool has_images = true;
};
template<>
struct traits<txt> {
static std::string get_title(txt& document) { return ""; } // Not supported
static std::string get_content(txt& document) { /* ... */ }
static bool has_images = false;
};
// Printers
class canon_printer : public printer {
template<typename T>
void print(T document) override
{
std::string title = traits<T>.get_title(document);
// ...
if (traits<T>.has_images)
// ...
}
};
To me, it looks quite powerful. As of now, I have only seen this concept in C++. Is there a similar concept in other programming languages? I'm more looking for a language independent term for this approach rather than a list of languages.
It depends on what you're using the traits for. For many uses, some
form of the strategy pattern would be an appropriate solution. You'll
get run time resolution, rather than compile time, and you can't really
use it to define types, however.
In your example, I'm not sure that you want traits even in C++. Your
function Printer::print is apparently virtual (since you override it
in a derived class), but is also a template; this is not legal in C++.
What you probably need is some variant of the bridge pattern, using
virtual functions even in C++. You might, for example, have an abstract
base class along the lines of:
class DocumentInformation
{
public:
virtual ~DocumentInformation() = default;
virtual std::string get_title() const = 0;
virtual std::string get_content() const = 0;
// ...
virtual bool has_images() const = 0;
};
Then for each document type, you derive a concrete instance:
class PDFDocumentInformation : public DocumentInformation
{
PDFDocument const& myDocument;
public:
PDFDocumentInformation( PDFDocument const& document )
: myDocument( document )
{
}
std::string get_title() const override
{
// ...
}
// ...
bool has_images() const override { return true; }
};
You're (virtual) Printer::print function then takes a
DocumentInformation const&, and uses it to obtain the information it
needs.
Depending on the way your code is organized, you might not even need the
bridge. It's often possible to have all of your concrete document
classes derived directly from an abstract Document, with the virtual
functions, and pass this to Printer::print. This is, in fact, the
usual case; the bridge is only needed if you have existing document
classes with incompatible interfaces.
I have a token class that looks something like this:
class Token
{
public:
typedef enum { STRTOK, INTTOK } Type;
virtual bool IsA(Type) = 0;
}
class IntTok : public Token
{
int data;
public:
bool IsA(Type t) { return (t == INTTOK); }
int GetData() { return data; }
}
IntTok newToken;
if ( newToken.IsA(Token::INTTOK )
{
//blah blah
}
So essentially I have to have every subclass defined in the Token class; which doesn't turn out that bad because there are very few subclasses and I can't imagine them changing. But still, it's ugly, kludgy and less "correct" than identifying subclasses using a dynamic cast. However:
IntTok newToken;
IntTok* tmpTokenTest = dynamic_cast<IntTok*>(&newToken);
if ( tmpTokenTest != NULL )
{
//blah blah
}
Is also pretty kludgy. Particularly when I have to string them together in a large, nested if.
So which would you use? Is there another solution to this problem?
Note: I know that I'll have to cast them to get at their respective data anyways, but
I won't be casting them until right before I use their function, so it feels cleaner and
I test their type far more often then I use their data.
Note2: Not indicated in the code above is that these tokens are also a linked list. That makes templating difficult(a Token<int> may point to a Token<string>, etc). Which is why I need a Token class as a parent to begin with.
Just use virtual functions instead to do what you want. Instead of this:
if(newToken.IsA(Token::INTTOK))
{
// do stuff with ((IntTok*)&newToken)->GetData()
}
Do this:
class Token
{
public:
...
virtual void doTypeDependentStuff() {} // empty default implementation
}
class IntTok : public Token
{
public:
...
void doTypeDependent()
{
// do stuff with data
}
}
Visitor pattern, indeed.
class TokenVisitor {
public:
virtual ~TokenVisitor() { }
virtual void visit(IntTok&) = 0;
virtual void visit(StrTok&) = 0;
};
class Token {
public:
virtual void accept(TokenVisitor &v) = 0;
};
class IntTok : public Token {
int data;
public:
virtual void accept(TokenVisitor &v) {
v.visit(*this);
}
int GetData() { return data; }
};
Then just implement the visitor interface and call
token->accept(myVisitor);
Control will be given to the Visitor, which then can do the appropriate action(s). If you need to have the variable locally and of the right type - then however you will hardly get around down-casting it. But i think driving control to specific implementations using virtual functions often is a good way to solve it.
Might i suggest using Boost::Variant, which is basically the union of multiple types (an object of type variant can hold any object of type Ti ( 1 <= i <= n ) ).
Using this, you won't have to use inheritance.
See there for more information.
So essentially I have to have every subclass defined in the Token class
Can you explain why?
Is it really necessary to cast? Polymorphic functions can be put to use.
Or, maybe you can have a templated Token class (with default behavior for some) and specialize for the remaining.
That's a nasty one, though I would be more likely to go with the version of using RTTI.
Weren't new C++ compilers (I've last tried in VC 6.0 when it wasn't really supported) supposed the typeid operator so you wouldn't need a full dynamic cast?