My C++ framework has Buttons. A Button derives from Control. So a function accepting a Control can take a Button as its argument. So far so good.
I also have List<T>. However, List<Button> doesn't derive from List<Control>, which means a function accepting a list of Controls can't take a list of Buttons as its argument. This is unfortunate.
Maybe this is a stupid question, but I don't see how can I solve this :( List<Button> should derive from List<Control>, but I don't see a way to make this happen "automatically".
Stroustrup has an item on this in his FAQ:
Why can't I assign a vector<Apple*> to a vector<Fruit*>
You can solve it in two ways:
Make the List contain pointers to Control . Then accept List<Control*>
Make your function a template. You can still use List<Button> and List<Control> then, but it's more boilerplate code, and not necassary most of the time.
Here is code for the second alternative. The first alternative is already explained by other answers:
class MyWindow {
template<typename T>
void doSomething(List<T> & l) {
// do something with the list...
if(boost::is_same<Control, T>::value) {
// special casing Control
} else if(boost::is_same<Button, T>::value) {
// special casing Button
}
}
};
To restrict doSomething only for List<derived from Control>, some more code is needed (look for enable_if if you want to know).
Note that this kind of code (looking what type you have) is rather to avoid. You should handle such things with virtual functions. Add a function doSomething to Control, and override it in Button.
I hate to tell you but if you're using a list of instances to Control instead of pointers to Control, your buttons will be garbage anyway (Google "object slicing"). If they're lists of pointers, then either make the list<button*> into list<control*> as others have suggested, or do a copy to a new list<control*> from the list<button*> and pass that into the function instead. Or rewrite the function as a template.
So if you previously had a function called doSomething that took a list of controls as an argument, you'd rewrite it as:
template <class TControl>
void doSomething( const std::list<TControl*>& myControls ) {
... whatever the function is currently doing ...
}
void doSomethingElse() {
std::list<Button*> buttons;
std::list<Control*> controls;
doSomething( buttons );
doSomething( controls );
}
How about using pointers? Just have a list of list<Control*> and put whatever Control-derived objects you like into it.
Instead of using List<Button>, use List<Control*>, which are pointing to Buttons.This way, your function only has to take one type: List<Control*>.
Generally, the C++ way to write algorithms that perform on a list, sequence, ... is to provide iterators as arguments.
template < class iterator >
doSomething(iterator beg, iterator end);
This solves the List< Button* > is not derived from List< Control* >. (using a template List< T* > would too, but that's kind of making your function generic-but-not-really)
In my experience, making good templatized functions operating on iterators can be a lot of (too much...) work, but it's the "C++ way"...
If you go this route, consider using Boost.ConceptCheck. It'll make your life a lot easier.
Related
First off, sorry for the title. I couldn't really condense what I'm trying to ask into one phrase :(
I was reading this post, and it somehow got me thinking on function pointers. Specifically, I was wondering why it's "bad" (or, at least, rarely seen) to pass class member functions as function parameters, and then use that pointer on an existing object within that function.
Let's assume I have a template class "Container", which stores a single variable of type T and provides a method to get a const reference to this variable.
template<class T>
class Container {
public:
Container(T anObject) {
m_data = anObject;
}
const T& getData() const {
return m_data;
}
private:
T m_data;
};
Now, I would like to be able to execute member functions of T on m_data, but I don't want to make getData() non-const because that would enable all kinds of other mischief with the returned reference. My solution is to add a new public function, modifyData(...), to Container, which takes a function pointer to a member function of T as a parameter and executes it on m_data; like so:
// ...
void modifyData( void(typename T::*funcptr)(void) ) {
(m_data.*fptr)();
}
// ...
As-is, this will crash and burn if T is a pointer. For testing, I just created a specialized template for Container<T*> to address this, but I'm sure there would be a more elegant way.
A very construed example shows that this seems to work as intended:
// example class to be used with Container
class Data {
public:
Data() {m_count = 0; }
void incrementCount() { m_count++; }
int getCount() const { return m_count; }
private:
int m_count;
};
// ... in main.cpp:
Data dat;
Container<Data*> DCont(dat);
std::cout << cl.getData()->getCount() << std::endl; // outputs 0
DCont.modifyData<Data>(&Data::incrementCount);
std::cout << cl.getData()->getCount() << std::endl; // outputs 1
// compiler catches this:
// DCont.modifyData<SomeOtherClass>(&Data::incrementCount);
// this probably does something bad:
// DCont.modifyData<SomeOtherClass>(&SomeOtherClass::someFunc);
Now, instinctively this just seems like a horribly twisted way of doing things, and I've never seen code that works like this. But my question is, is there a performance/security reason why something like this is bad, or is it something that's just considered bad practice? If it's "just" bad practice, then why is that?
Obvious limitations that I could think of are that something like
// DCont.modifyData(&SomeOtherClass::someFunc);
will probably crash at runtime, but I think that could be addressed by checking the type of U against T in incrementData(). Also, as it is, modifyData only accepts void (*)() functions, but this could probably be addressed with variadic templates.
This example is obviously very construed and not implemented so well, but I think (hope?) it's good enough to explain what I'm talking about.
Thanks!
EDIT: There seems to be some confusion as to what the question is. Basically, this is the scenario I'm talking about: You have a bunch of classes from some library that you're trying to store in the container, and another function that generates certain containers; Now, you want the user to be able to call existing member functions on the objects within these containers, but not to modify the actual objects (like when returning a non-const reference with the getter). An actual implementation would probably use some sort of variadic template to be useful, but I need to think that through some more before posting example code.
In short, I'd like to limit a user's access to container members to only member functions of that member. Is there an easier way of doing this, or does this way not work in the way I was intending?
I don't have any problem with your architecture - I don't see it as bad practice. To me it seems quite a laborious way to protect data and doesn't really help you much in that the user can use any void function to modify the contained data which isn;t really a contract on what can and can't be changed.
I think the reason this construct is so rarely seen is that your requirement and goals of the container class are unusual.
I'm new to C++, and unfortunately I cannot stop thinking in C# (my former language).
I read some books, forums and the C++ reference website, but I couldn't find an answer to my question, so I thought I might as well try here before giving up and writing something ugly.
Ok, we can start.
I have a class with an abstract method succesorsFunction and I would like it to return a collection of pointers to State. I don't want to force the implementors to a specific container; I rather let them choose (vector, list, etc).
So it looks like this:
class Problem
{
public:
virtual list<const State*>::iterator succesorsFunction(const State &state, list<const State*>::iterator result) const = 0;
};
the problem here is the explicit use of list. How do you do it in C++?
I thought about using templates, but then I encountered two problems:
1) It seems like you cannot do it with abstract methods (or am I wrong?)
2) How do I tell the template it should contain pointers to State?
You can't overload methods based on return types in C++.
Also, "containers" in C++ don't have the same base (like Collection in Java), so you can't return a generic container.
I'm afraid there's no clean way of doing this.
I would just write overloads (by parameter) or different function names.
For your questions:
1) You can. What makes you think you can't?
2) The same way you declared list: list<const State*> - const is optional.
If you really want to enforce STL container usage, try the following:
template <template <typename,
typename = std::allocator<const State *> > class Container>
Container<const State*> successorsFunction(const State &state, const Container<const State*> &c) const
{
// return something useful.
}
If you insist on having this function be virtual, then it can't be a member function template, just overload it with the types you intend to support, then you can make them virtual.
You can't have a member function template which is virtual, but you can try implement friend generic function like this:
template <typename yourType>
yourType& succesorsFunction(const State &a, yourType &result){//Your return type can be without reference
//Your body
return result;
}
If you call your function for example with vector<State> a argument like this:
sucessorsFunction(b,a);// b is your State object
deduction process will automatically conclude that yourType is actually vector<State> type, which I think resolves your problem. Also, this arhitecture aloves you to create for example new class type MyVector (which holds arrays of States) and pass MyVector object to succesorsFunction.
This is just an elaboration to C.T's answer. Please remember that if you return a container of pointers then you will have to release them explicitly or use std::unique_ptr .
Just a FYI.. as you are from C# background.
You could use State or templatize it as well.
template<typename Type,
template< typename, typename = std::allocator<Type*> > class Container
>
Container<Type*> Successor(const Type& x)
{
Container<Type*> cont;
// something.
cont.push_back(new Type(x));
return cont;
}
and call it
vector<State*> states = Successor<State, vector>(State(10));
The project I'm working on has some pretty nasty collection classes that I feel could use a redesign. I'd really like to make a collection template class that takes model instances and provides a way to call type-specific functions of each child in the collection. For example, something like:
MyCollection<Student> BiologyStudents();
// [Fill the collection]
BiologyStudents.EnrollInClass(ClassList::Biology);
BiologyStudents.Commit();
The idea is that I could easily enroll all students in a class using my collection, then commit those changes to a database. My problem is in how to expose that EnrollInClass() function which belongs to the children Student objects? If my collection contains objects of a different type than Student, I would like those functions to be exposed from the collection. The only way I can think to do that with my semi-limited C++ knowledge would be to make a function that takes a parameter which references a function I know is in the containing child class. This wouldn't provide compilation errors if you call the wrong function or provide the wrong parameters, so I'd like a way to utilize the compiler to provide these checks.
Is this possible? If so, how? As a warning, I'm used to generic programming in Java/C#, so my impression of C++ templates might be a bit off.
One way would be to use a method pointer:
template <typename T>
struct MyCollection {
template <typename U>
void ForEach(void (T::*func)(U),U param)
{
// for each item loop goes here
(item.*func)(param);
}
};
MyCollection<Student> BiologyStudents;
// [Fill the collection]
BiologyStudents.ForEach(&Student::EnrollInClass,ClassList::Biology);
You would have to provide different versions for different numbers of parameters.
With C++11, you can do this:
template <typename T>
struct MyCollection {
void ForEach(std::function<void (T &)> func)
{
// for each item loop goes here
func(item);
}
};
MyCollection<Student> BiologyStudents;
// [Fill the collection]
BiologyStudents.ForEach([](Student &s){s.EnrollInClass(ClassList::Biology);});
Which would not require making different versions of ForEach for different numbers of parameters.
I'm making a Gui API for games. Basically I have event callbacks in my class which are function pointers. I thought of directly letting the user = the function pointer ex:
widget->OnPaintCallback = myPaintFunc;
But I don't like how I cannot check for NULL or do anything else. It also makes my class feel exposed.
I also thought of having a setter for each callback, but that will get messy in the class (I have over 50)
I then thought of a function that asks for a string indicating which event the handler is for, and its function pointer. But that would evolve needlessly referencing documentation to know the string, and even more confusing for custom undocumented widgets.
Is there a better, cleaner alternative?
Thanks
Could casablankca's solution have multiple arguments?
I would suggest the Boost.Signals library. Something like this:
class Widget
{
public:
boost::signal<void (Paint &)> onPaint;
boost::signal<void (MouseMove &)> onMouseMove;
// ... etc
};
// later...
Widget myWidget;
myWidget.onPaint.connect(myPaintFunc);
// and to fire the event:
void Widget::DoPaint()
{
Paint data;
data.whatever = foo;
onPaint(data);
}
This has several advantages:
You can combine it with boost::bind (or C++0x version of bind if your compiler supports it) to allow you to bind member functions to event handlers.
You can attach multiple handlers to a single event. If you just use function pointers, then only a single function pointer can be assigned at a time.
The signals are strong-typed and flexible. You can have signals which take different types and numbers of parameters, and they'll all be resolved at compile-time.
I recommend taking a look at the boost.signals library, or libsigc++. These are very general libaries for managing things like event handlers. They do a lot more than what you are trying to do, but they'll give you ideas for what you may want from your design that you haven't thought of yet.
The more you use your callbacks the more you'll realize that you want more of the features in those libraries (like registering multiple callbacks, binding arguments, being more flexible with types, etc.) So even if you end up doing something simpler, it will be helpful to learn from mature designs.
But I don't like how I cannot check for NULL or do anything else
How about making the callback (OnPaintCallback) an object of a class that overloads operator =, that way you can do any additional checking and throw an exception if something goes wrong. You can also overload operator () so that you can call this object as if it were a simple function pointer.
Update: As for variable number of function arguments, there is no general way to do it, but if your maximum N is limited and small, you could use template specializations, for example: (I've omitted constructors, operator = and other details for clarity)
template<typename T, int N>
class Callback {
};
template<typename T>
class Callback<T, 1> {
T func;
template<typename A1>
void operator ()(A1 arg1) {
func(arg1);
}
};
template<typename T>
class Callback<T, 2> {
T func;
template<typename A1, typename A2>
void operator ()(A1 arg1, A2 arg2) {
func(arg1, arg2);
}
};
I know this is a hacky way to do it but at least your users won't see any of this: they'll get the same interface for all callbacks.
You can do an interface for each type of event handler you need. Not unlike Java does it. So for example you would have
class PaintCallback {
public:
virtual void paint() = 0;
};
Your event handler would inherit from the abstract class and implement the paint method. In the widget class you would keep a pointer (or a collection) for each handler.
I have a program which is built on "Entities", which hold "Components" (composition FTW).
Components may include many different types including scripts, assets, etc. I would like to build an Entity function called
Entities have a map of strings, and actual Components, such that the Components can be searched for by type name.
I would like to have a function called
<Component T>GetComponent(char* TypeName, <T>);
Which takes in a string and a type name, and which returns the typed component that is requested.
Is it possible to do such a thing with C++ templates? The above clearly does not work, and I'm not sure how to go about it.
Thanks
Edit:
I'm not looking for a factory.
Entity holds instances of different types of components. Currently this is done with
std::vector<Component> componentList;
and an
std::vector<char*> componentNames;
Whose indexes are guaranteed to be the same. Likely I will write a proper map later.
I simply want GetComponent to return a properly typed reference to the already instantied component of type name held by Entity in the ComponentList.
Does your function create components? Then it is a factory. You could wrap it in that template in order to save clients the (potentially erroneous) casting.
The type of the function template would look like this:
template< typename T >
T* GetComponent(const char*); // presuming it returns a pointer
and it would be called like this:
Foo* foo = GetComponent<Foo>("foo");
Asking the proper question is at least half of the way to getting a good answer. You should really state what you want to achieve rather than the particular problem you are facing. It seems to me as if you have more problems with the language than you actually realize.
The first part is that it seems as if you have a component hierarchy that derives from Component, probably providing a common interface. An entity holds many components internally, that can be of any derived type from Component. If that is the case, you should rework your containers as you are storing Component objects directly, and that will produce slicing in your objects (no matter what derived type you enter into the container, the container will only keep the common Component part of the object).
Working on a couple of vectors and hoping that both of them will be synchronized at all times is feasible but fragile. If the name and the component go together, then you want to store pairs of name/component. If you want to search by name, you should use a map as it will provide O(log N) search directly.
Now, going back to the question. If what you want to achieve is plain syntactic sugar (avoid the caller from explicitly dynamic casting if needed) then you can get it with a template (more later on). But you should really think on your design. Does Component define the real interface into any component? If users need to downcast to particular types before using a Component, either the abstraction is bad (Component does not provide a real interface) or the objects do not really fit together.
If at the end of it you still want to do it, you can hide the dynamic cast from the caller by doing it within a template method (or free function).
class Entity {
typedef std::map< std::string, boost::shared_ptr<Component> > component_map_t;
public:
boost::shared_ptr<Component> getComponent( std::string const & name ) {
component_map_t::iterator it = components_.find(name);
if ( it == components_.end() ) { // not found, handle error
// ...
}
return it->second;
}
template <typename T> // syntactic sugar
boost::shared_ptr<T> getComponent( std::string const & name ) {
return boost::dynamic_pointer_cast<T>( getComponent(name) );
}
private:
component_map_t components_;
};
template <typename T> // syntactic sugar also available as free function
boost::shared_ptr<T> getComponent( Entity & entity, std::string const & name ) {
return boost::dynamic_pointer_cast<T>( entity.getComponent(name) );
}
int main() { // usage
Entity e; // ... work with it add components...
boost::shared_ptr<Component> c1 = e.getComponent( "one" ); // non-templated method returns Component
boost::shared_ptr<DerivedComponent> c2 = e.getComponent<DerivedComponent>( "two" );
boost::shared_ptr<DerivedComponent> c3 = getComponent<DerivedComponent>( e, "two" );
}
You could play with the interface so that instead of boost::shared_ptr you return real references (with what it entails: lifetime must be carefully controlled so that user code does not try to use a dangling reference if the component is removed from the entity).
You could use something like:
struct Entity
{
Component* GetBaseComponent (const char* TypeName)
{
// do lookup on TypeName and return corresponding Component.
}
template<typename T> T* GetComponent (const char* TypeName)
{
return dynamic_cast<T*> (GetBaseComponent (TypeName));
}
};
and call it with something like:
entity.GetComponent<MyComponent> ("MyComponent");
If you ask for a component and get the type wrong the cast will return a null ptr.
Edit: Just realised this is essentially the same solution as sbi, albeit without calling it a factory.
Your getComponent function has two separate tasks
1) retrieve an object from a string identifier
2) cast this object into the provided template argument type
Using templates makes (2) pretty straight forward. But (1) needs work on string objects, so templates won't do the trick on their own. You have got to fill your component container some other way. As for storing and casting, you may be interested in boost::any or boost::variant.