Sorry for my poor english I'll try to do my best.
I want to design an interface that should be used like this:
class MyObject : public IMyInterface<MyObject>
{
// ...
};
The interface could look like this:
template <class _TMyObject>
class IMyInterface
{
virtual _TMyObject* Get() = 0;
};
What i'm looking after, is a way to verify, at compile time, that the interface is used as intended.
How can I test if _TMyObject "is-a" IMyInterface<_TMyObject>? Inside the interface definition, with a static_assert for example.
Thanks for any help :).
Have a nice day!
You can't put static_assert inside the class itself, because D is an incomplete type, but you can put it in the destructor (or constructor, but there can be many constructors):
template<class D>
struct B
{
~B()
{
static_assert(std::is_base_of_v<B, D>);
};
};
struct Not_E {};
struct D : B<D> { };
struct E : B<Not_E> { };
void foo()
{
D d; // OK
E e; // Fails
}
Addition. Note that this solution is not a complete protection against incorrect usage of CRTP. Please refer to Some Programmer Dude's answer for a nice example of error that can't be caught by it.
Since C++11 there are many type property traits that could be used to do checks at compile-time.
For example std::is_base_of which in your case could be used like perhaps
template<typename TChild>
struct IMyInterface
{
static_assert(std::is_base_of<IMyInterface, TChild>::value, "Derived class not derived from IMyInterface");
// ...
};
Note: The exact code shown above will not work directly, but rather show the principle.
Of course, that do allow something like
class MyFirstClass : public IMyInterface<MyFirstClass>
{
// ...
};
// Note wrong class in template
// vvvvvvvvvvvv
class MySecondClass : public IMyInterface<MyFirstClass>
{
// ...
};
So to answer your question if it's possible for such a check: Not really the way you want. Even using other traits and meta-programming, you can never guarantee that the template argument for the interface class is "correct" when used in the CRTP.
The only way I can see it work is by using down-casting at run-time with dynamic_cast, something like dynamic_cast<TChild*>(this) != nullptr in the interface class.
Related
I am having difficulty understanding the piece of code given below.
class Child1 : public Base1 {
public:
int Func1(char *Var);
}
class Cls_X: public std::enable_shared_from_this<Cls_X> {
public:
void Func2(char *Var_copy);
}
Func2 is called from Func1 as below
int Func1(char * Var){
...
make_shared<Cls_X>(ioc, ctx)->Func2(Varcopy_ptr);
...
}
Questions:
How class Cls_X: public std::enable_shared_from_this<Cls_X> works?
Tried googling but couldn't understand the documentation for this, Can someone explain in simple english?
Are Cls_X and Child1 both derived class of Base1 here?
NOTE:
The tag [boost] is added because the code example is taken from one of the boost libraries. Please check the example to see how shared_from_this is used in the program
Ps 1:- Change the suitable title if possible.
How class Cls_X: public std::enable_shared_from_this<Cls_X> works?
It can work iff the specialization of the template class (here std::enable_shared_from_this<Cls_X>) does not need to receive a type parameter (here Cls_X) that is a complete type.
template <typename T>
struct has_a_member { T mem; };
template <typename T>
struct has_a_pointer { T *ptr; };
struct A : has_a_member<A> // error at this point:
// A is incomplete at this point
// the definition of has_a_member<A> cannot be instantiated
{
};
struct B : has_a_pointer<B> // OK, B is incomplete
// still has_a_pointer<B> can be instantiated
{
};
And enable_shared_from_this is designed to work in that case, by expecting an incomplete type.
I am having trouble finding a fix for the following error, thrown when compiling a std::static_pointer_cast<>():
error: invalid static_cast from type ecse::EventSubscriptionManager<ecse::BaseEvent>* to type ecse::EventSubscriptionManager<TestEvent>*
I have the following hierarchy. In the end they will be filled with POD type members and will most likely become structs.
class BaseEvent {};
template <class E>
class Event : public BaseEvent, public Type<E> {};
class TestEvent : public Event<TestEvent> {};
I am currently working on the Subscribe function part of the EventManager, however when compiling I am receiving the error posted above. Note: E::ID() is defined in the class as Type and is used for identifying the class type.
template <class E>
class EventSubscriptionManager
{
public:
void Subscribe(std::function<void(E)> fptr);
private:
std::function<void(E)> event_function_;
};
class EventManager
{
public:
template <class E>
void Subscribe(std::function<void(E)> fptr)
{
std::shared_ptr<EventSubscriptionManager<E>> sub_manager_ptr;
auto sub_manager_iterator = sub_managers_.find(E::ID());
if(sub_manager_iterator == sub_managers_.end())
{
sub_manager_ptr = std::make_shared<EventSubscriptionManager<E>>();
}
else
{
sub_manager_ptr = std::static_pointer_cast<EventSubscriptionManager<E>>(sub_manager_iterator->second);
}
// Continue function...
}
private:
std::unordered_map<std::size_t, std::shared_ptr<EventSubscriptionManager<BaseEvent>>> sub_managers_;
}
I believe that the issue is that between the TestEvent and the BaseEvent there is the Event<E> class with the template, with TestEvent inheriting Event<TestEvent> instead of BaseEvent. Is this true? If so, how can I set up my hierarchy to allow for this type of casting?
If that is not the case, what is the issue with the above static cast?
I can tell you why it does not compile. This is because
EventSubscriptionManager<E>
is unrelated to
EventSubscriptionManager<BaseEvent>
So, according to point 1.) on the reference page,
static_cast<EventSubscriptionManager<E>*>((EventSubscriptionManager<BaseEvent>*)nullptr)
is ill-formed.
However, without knowing the background I can't tell what to do as a workaround.
Just: you have to relate the two classes, or choose a completely new design.
In order to do so, here is a minimal example why it fails which might be helpful:
struct Base {};
struct Derived : Base {};
template<typename T>
struct Foo {};
int main()
{
static_cast<Foo<Derived>*>((Foo<Base>*)nullptr);
}
You can try to improve on that.
In C++, there is no covariance or contravariance, there is no relationship between T<Base> and T<Sub>, even if there is one between Base and Sub.
You either need to build a common ancestor of different EventSubscriptionManager instances (e.g: EventSubscriptionManagerBase), and use that, or provide a converting constructor.
I'm subclassing std::shared_ptr and am trying to write a cast() method on the subclass so I can hide static_pointer_cast, but I can't get my code to compile. What am I missing?
Demo: http://ideone.com/nbPHbs
template<class T>
class Handle : public std::shared_ptr<T> {
public:
template<class ResultType>
inline Handle<ResultType>
cast() {
// Cast Handle to shared_ptr
auto T_sp = static_cast< std::shared_ptr<T> >(*this);
// Cast the data
auto ResultType_sp = std::static_pointer_cast<ResultType>(T_sp);
// Cast back to Handle
return static_cast< Handle<ResultType> >(ResultType_sp);
}
};
// Usage
struct Base {};
struct Child : public Base {};
auto child_ptr = Handle<Child>(new Child());
auto base_ptr = child_ptr.cast<Base>(); // Error with this
This is the Error message I get:
error: no matching function for call to 'Handle<Child>::Handle(Child*)'
auto child_ptr = Handle<Child>(new Child());
^
**EDIT
I'm using inheritance here because it was write-once/throw-away code that was originally template<T> using std::shared_ptr<T> Handle<T>; So, inheritance was the natural progression that required the least amount of code changes. Since it did look like this piece of code will stick around a little longer, I did switch to composition before posting this SO question, I just wanted to know why it wasn't compiling; I haven't done any c++ in a few years, so my skills are a little rusty.
This answer is skipping the discussion as to whether inheriting from std::shared_ptr is a good idea or not. I would though recommend reading such discussion before continuing further.
Now to your immediate problem:
If you really want to continue this route then what you are missing is the constructors.
The compiler is only creating a default constructor for you.
As the error message shows you need Handle<Child>::Handle(Child*).
The easiest way to get the needed constructors would be to reuse the ones from the base class:
template<class T>
class Handle : public std::shared_ptr<T> {
public:
using std::shared_ptr<T>::shared_ptr;
...
I dont see any advantage of inheriting shared_ptr here, its not worth the trouble imho. if you think std::static_pointer_cast is big and ugly, you can solve that by an inline function
template <typename TOUT, typename TIN>
inline std::shared_ptr<TOUT> cast(TIN in)
{
return std::static_pointer_cast<TOUT>(in);
}
// Usage
struct Base {};
struct Child : public Base {};
int main() {
std::shared_ptr<Child> child_ptr = std::make_shared<Child>();
std::shared_ptr<Base> base_ptr = cast<Base>(child_ptr); // Error with this
return 0;
}
Your class does not have any constructor, therefore, when you try to compile, it will miserably fail if you try to use a constructor with arguments.
If you wanted to inherit from shared_ptr (which I disencourage, because base destructor is not virtual and your program most likely will leak memory heavily) you should add this line in your class body:
using std::shared_ptr<T>::shared_ptr;
I'm trying to create a vector (or any STL container, really) that could hold a set of various objects that are subclasses of one specific type. The problem is that my base class is templated.
From what I can tell, I have to create an interface/abstract super base class (not sure what the preferred C++ terminology is). I'd prefer not to do this, and just use my (templated) abstract base class. Below is some example code.
Basically, is there a way not to require the WidgetInterface? Someway to tell the compiler to ignore template requirements? If I must have WidgetInterface, am I going the right way with the following?
#include <vector>
#include "stdio.h"
enum SomeEnum{
LOW = 0,
HIGH = 112358
};
// Would like to remove this WidgetInterface
class WidgetInterface{
public:
// have to define this so we can call it while iterating
// (would remove from Widget if ended up using this SuperWidget
// non-template baseclass method)
virtual void method() = 0;
};
template <class TDataType>
class AbstractWidget : public WidgetInterface{
public:
TDataType mData;
virtual void method() = 0;
// ... bunch of helper methods etc
};
class EnumWidget : public AbstractWidget<SomeEnum>{
public:
EnumWidget(){
mData = HIGH;
}
void method(){
printf("%d\n", mData); // sprintf for simplicity
}
};
class IntWidget : public AbstractWidget<int>{
public:
IntWidget(){
mData = -1;
}
void method(){
printf("%d\n", mData); // sprintf for simplicity
}
};
int main(){
// this compiles but isn't a workable solution, not generic enough
std::vector< AbstractWidget<int>* > widgets1;
// only way to do store abitary subclasses?
std::vector<WidgetInterface*> widgets2;
widgets2.push_back(new EnumWidget());
widgets2.push_back(new IntWidget());
for(std::vector<WidgetInterface*>::iterator iter = widgets2.begin();
iter != widgets2.end(); iter++){
(*iter)->method();
}
// This is what i'd _like_ to do, without needing WidgetInterface
// std::vector< AbstractWidget* > widgets3;
return 0;
}
No, you can't use directly AbstractWidget as a parameter of STL container or anything else.
The reason is that class AbstractWidget does not exist. It is only a template for compiler to construct classes from.
What exists is AbstractWidget<SomeEnum> and AbstractWidget<int> only because of EnumWidget and IntWidget inheriting from them.
Templates exist at compiler-level only. If AbstractWidget<T> weren't used anywhere in your code, there would be no traces of it during the runtime.
Therefore, the code you posted seems to be the best (if not only) solution for your problem.
What you've done is the solution: you need a common class/interface, and since AbstractWidget is class template, therefore it cannot be used as common class for all concrete classes for which the template argument is different. So I think, you should go with this class design. It seems to be quite reasonable solution.
In fact the classes AbstractWidget<int> and AbstractWidget<double> are different classes, so your class IntWidget is a subclass of the first but is in no relation with the second. You need to have a common parent class to put in the vector so unfortunately you can not avoid the common interface that is not templated.
This could be completely in the wrong direction, but could you do something like this:
template <class T>
class ConcreteWidget : public AbstractWidget<T>
{
};
and then use template specialization to define your specific widgets like this:
template <>
class ConcreteWidget : public AbstractWidget<int>
{
public:
ConcreteWidget() : mData(-1) {}
};
template <>
class ConcreteWidget : public AbstractWidget<SomeEnum>
{
public:
ConcreteWidget() : mData(HIGH) {}
};
So rather than having an IntWidget and an EnumWidget, you'd have a ConcreteWidget and ConcreteWidget and then could simply have a vector<WidgetInterface> that would be the super of all of these generic children?
I'm not sure if this solves your problem, or would even work. I'd love feedback on this answer.
I'm finding it difficult to describe this problem very concisely, so I've attached the code for a demonstration program.
The general idea is that we want a set of Derived classes that are forced to implement some abstract Foo() function from a Base class. Each of the derived Foo() calls must accept a different parameter as input, but all of the parameters should also be derived from a BaseInput class.
We see two possible solutions so far, neither we're very happy with:
Remove the Foo() function from the base class and reimplement it with the correct input types in each Derived class. This, however, removes the enforcement that it be implemented in the same manner in each derived class.
Do some kind of dynamic cast inside the receiving function to verify that the type received is correct. However, this does not prevent the programmer from making an error and passing the incorrect input data type. We would like the type to be passed to the Foo() function to be compile-time correct.
Is there some sort of pattern that could enforce this kind of behaviour? Is this whole idea breaking some sort of fundamental idea underlying OOP? We'd really like to hear your input on possible solutions outside of what we've come up with.
Thanks so much!
#include <iostream>
// these inputs will be sent to our Foo function below
class BaseInput {};
class Derived1Input : public BaseInput { public: int d1Custom; };
class Derived2Input : public BaseInput { public: float d2Custom; };
class Base
{
public:
virtual void Foo(BaseInput& i) = 0;
};
class Derived1 : public Base
{
public:
// we don't know what type the input is -- do we have to try to cast to what we want
// and see if it works?
virtual void Foo(BaseInput& i) { std::cout << "I don't want to cast this..." << std::endl; }
// prefer something like this, but then it's not overriding the Base implementation
//virtual void Foo(Derived1Input& i) { std::cout << "Derived1 did something with Derived1Input..." << std::endl; }
};
class Derived2 : public Base
{
public:
// we don't know what type the input is -- do we have to try to cast to what we want
// and see if it works?
virtual void Foo(BaseInput& i) { std::cout << "I don't want to cast this..." << std::endl; }
// prefer something like this, but then it's not overriding the Base implementation
//virtual void Foo(Derived2Input& i) { std::cout << "Derived2 did something with Derived2Input..." << std::endl; }
};
int main()
{
Derived1 d1; Derived1Input d1i;
Derived2 d2; Derived2Input d2i;
// set up some dummy data
d1i.d1Custom = 1;
d2i.d2Custom = 1.f;
d1.Foo(d2i); // this compiles, but is a mistake! how can we avoid this?
// Derived1::Foo() should only accept Derived1Input, but then
// we can't declare Foo() in the Base class.
return 0;
}
Since your Derived class is-a Base class, it should never tighten the base contract preconditions: if it has to behave like a Base, it should accept BaseInput allright. This is known as the Liskov Substitution Principle.
Although you can do runtime checking of your argument, you can never achieve a fully type-safe way of doing this: your compiler may be able to match the DerivedInput when it sees a Derived object (static type), but it can not know what subtype is going to be behind a Base object...
The requirements
DerivedX should take a DerivedXInput
DerivedX::Foo should be interface-equal to DerivedY::Foo
contradict: either the Foo methods are implemented in terms of the BaseInput, and thus have identical interfaces in all derived classes, or the DerivedXInput types differ, and they cannot have the same interface.
That's, in my opinion, the problem.
This problem occured to me, too, when writing tightly coupled classes that are handled in a type-unaware framework:
class Fruit {};
class FruitTree {
virtual Fruit* pick() = 0;
};
class FruitEater {
virtual void eat( Fruit* ) = 0;
};
class Banana : public Fruit {};
class BananaTree {
virtual Banana* pick() { return new Banana; }
};
class BananaEater : public FruitEater {
void eat( Fruit* f ){
assert( dynamic_cast<Banana*>(f)!=0 );
delete f;
}
};
And a framework:
struct FruitPipeLine {
FruitTree* tree;
FruitEater* eater;
void cycle(){
eater->eat( tree->pick() );
}
};
Now this proves a design that's too easily broken: there's no part in the design that aligns the trees with the eaters:
FruitPipeLine pipe = { new BananaTree, new LemonEater }; // compiles fine
pipe.cycle(); // crash, probably.
You may improve the cohesion of the design, and remove the need for virtual dispatching, by making it a template:
template<class F> class Tree {
F* pick(); // no implementation
};
template<class F> class Eater {
void eat( F* f ){ delete f; } // default implementation is possible
};
template<class F> PipeLine {
Tree<F> tree;
Eater<F> eater;
void cycle(){ eater.eat( tree.pick() ); }
};
The implementations are really template specializations:
template<> class Tree<Banana> {
Banana* pick(){ return new Banana; }
};
...
PipeLine<Banana> pipe; // can't be wrong
pipe.cycle(); // no typechecking needed.
You might be able to use a variation of the curiously recurring template pattern.
class Base {
public:
// Stuff that don't depend on the input type.
};
template <typename Input>
class Middle : public Base {
public:
virtual void Foo(Input &i) = 0;
};
class Derived1 : public Middle<Derived1Input> {
public:
virtual void Foo(Derived1Input &i) { ... }
};
class Derived2 : public Middle<Derived2Input> {
public:
virtual void Foo(Derived2Input &i) { ... }
};
This is untested, just a shot from the hip!
If you don't mind the dynamic cast, how about this:
Class BaseInput;
class Base
{
public:
void foo(BaseInput & x) { foo_dispatch(x); };
private:
virtual void foo_dispatch(BaseInput &) = 0;
};
template <typename TInput = BaseInput> // default value to enforce nothing
class FooDistpatch : public Base
{
virtual void foo_dispatch(BaseInput & x)
{
foo_impl(dynamic_cast<TInput &>(x));
}
virtual void foo_impl(TInput &) = 0;
};
class Derived1 : public FooDispatch<Der1Input>
{
virtual void foo_impl(Der1Input & x) { /* your implementation here */ }
};
That way, you've built the dynamic type checking into the intermediate class, and your clients only ever derive from FooDispatch<DerivedInput>.
What you are talking about are covariant argument types, and that is quite an uncommon feature in a language, as it breaks your contract: You promised to accept a base_input object because you inherit from base, but you want the compiler to reject all but a small subset of base_inputs...
It is much more common for programming languages to offer the opposite: contra-variant argument types, as the derived type will not only accept everything that it is bound to accept by the contract, but also other types.
At any rate, C++ does not offer contravariance in argument types either, only covariance in the return type.
C++ has a lot of dark areas, so it's hard to say any specific thing is undoable, but going from the dark areas I do know, without a cast, this cannot be done. The virtual function specified in the base class requires the argument type to remain the same in all the children.
I am sure a cast can be used in a non-painful way though, perhaps by giving the base class an Enum 'type' member that is uniquely set by the constructor of each possible child that might possibly inherit it. Foo() can then check that 'type' and determine which type it is before doing anything, and throwing an assertion if it is surprised by something unexpected. It isn't compile time, but it's the closest a compromise I can think of, while still having the benefits of requiring a Foo() be defined.
It's certainly restricted, but you can use/simulate coviarance in constructors parameters.