So I'm making a application framework, every class basically inherits YObject, my Application manager handles any object that gets added to the class and stores them in: vector Application::ApplicationObjects`, I want to make a function like
ObjectType* object = Application->object_of<ObjectType>();
I'm not really sure how exactly to do this, I've heard one of the C++ casts can be used to determine if ObjectType derives from YObject, but I'm not sure!
EDIT:
Since its important to make understandable questions that can be researched or whatever..
What I was trying to make was a template function that would loop through all available objects and check if the current object could be cast to the template defined type.
I believe that you may have already found your answer here, but it may be beneficial to spell out how to do this for anyone else having the same issue.
You say that you want to:
Make was a template function that would loop through all available objects and check if the current looped object could be dereferenced to the template defined type
So let's start by assuming that you have pointers to all available objects in vector<YObject*> Application::m_foo, and you have pointers to a bunch of different objects in Application::m_foo.
You'll want to design your templated class like this:
template<typename T>
T* Application::object_of() {
T* result = nullptr;
for(auto& i : m_foo) {
T* bar = dynamic_cast<T*>(i);
if(bar != nullptr) {
result = bar;
break;
}
}
return result;
}
You can see a hacky example of this here: http://ideone.com/J4oA1j I say "hacky" cause rather than having an Application class I've just used a global variable, and I never delete my news. But I believe that the idea is clear.
Related
I hope the headline isn't too confusing. What I have is a class StorageManager containing a list of objects of classes derived from Storage. Here is an example.
struct Storage {}; // abstract
class StorageManager
{
private:
map<string, unique_ptr<Storage>> List; // store all types of storage
public:
template <typename T>
void Add(string Name) // add new storage with name
{
List.insert(make_pair(Name, unique_ptr<Storage>(new T())));
}
Storage* Get(string Name) // get storage by name
{
return List[Name].get();
}
};
Say Position is a special storage type.
struct Position : public Storage
{
int X;
int Y;
};
Thanks to the great answers on my last question the Add function already works. What I want to improve is the Get function. It reasonable returns a pointer Storage* what I can use like the following.
int main()
{
StorageManager Manager;
Manager.Add<Position>("pos"); // add a new storage of type position
auto Strge = Manager.Get("pos"); // get pointer to base class storage
auto Pstn = (Position*)Strge; // convert pointer to derived class position
Pstn->X = 5;
Pstn->Y = 42;
}
It there a way to get rid of this pointer casting by automatically returning a pointer to the derived class? Maybe using templates?
use:
template< class T >
T* Get(std::string const& name)
{
auto i = List.find(name);
return i == List.end() ? nullptr : static_cast<T*>(i->second.get());
}
And then in your code:
Position* p = Manager.Get<Position>("pos");
I don't see what you can do for your Get member function besides what #BigBoss already pointed out, but you can improve your Add member to return the used storage.
template <typename T>
T* Add(string Name) // add new storage with name
{
T* t = new T();
List.insert(make_pair(Name, unique_ptr<Storage>(t)));
return t;
}
// create the pointer directly in a unique_ptr
template <typename T>
T* Add(string Name) // add new storage with name
{
std::unique_ptr<T> x{new T{}};
T* t = x.get();
List.insert(make_pair(Name, std::move(x)));
return t;
}
EDIT The temporary prevents us from having to dynamic_cast.
EDIT2 Implement MatthieuM's suggestion.
You can also further improve the function by accepting a value of the
type to be inserted, with a default argument, but that might incur an
additional copy.
When you have a pointer or reference to an object of some class, all you know is that the actual runtime object it references is either of that class or of some derived class. auto cannot know the runtime type of an object at compile time, because the piece of code containing the auto variable could be in a function that is run twice -- once handling an object of one runtime type, another handling an object with a different runtime type! The type system can't tell you what exact types are in play in a language with polymorphism -- it can only provide some constraints.
If you know that the runtime type of an object is some particular derived class (as in your example), you can (and must) use a cast. (It's considered preferable to use a cast of the form static_cast<Position*>, since casts are dangerous, and this makes it easier to search for casts in your code.)
But generally speaking, doing this a lot is a sign of poor design. The purpose of declaring a base class and deriving other class types from it is to enable objects of all of these those types to be treated the same way, without casting to a particular type.
If you want to always have the correct derived type at compile time without ever using casts, you have no choice but to use a separate collection of that type. In this case, there is probably no point deriving Position from Storage.
If you can rearrange things so that everything that a caller of StorageManager::Get() needs to do with a Position can be done by calling functions that don't specify Position-specific information (such as co-ordinates), you can make these functions into virtual functions in Storage, and implement Position-specific versions of them in Position. For example, you could make a function Storage::Dump() which writes its object to stdout. Position::Dump() would output X and Y, while the implementations of Dump() for other conceivable derived classes would output different information.
Sometimes you need to be able to work with an object that could be one of several essentially unrelated types. I suspect that may be the case here. In that case, boost::variant<> is a good way to go. This library provides a powerful mechanism called the Visitor pattern, which allows you to specify what action should be taken for each of the types that a variant object could possibly be.
Apart from the fact that this looks like a terrible idea... let's see what we can do to improve the situation.
=> It's a bad idea to require default construction
template <typename T>
T& add(std::string const& name, std::unique_ptr<T> element) {
T& t = *element;
auto result = map.insert(std::make_pair(name, std::move(element)));
if (result.second == false) {
// FIXME: somehow add the name here, for easier diagnosis
throw std::runtime_error("Duplicate element");
}
return t;
}
=> It's a bad idea to downcast blindly
template <typename T>
T* get(std::string const& name) const {
auto it = map.find(name);
return it != map.end() ? dynamic_cast<T*>(it->second.get()) : nullptr;
}
But frankly, this system is quite full of holes. And probably unnecessary in the first place. I encourage you to review the general problem an come up with a much better design.
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 am struggling to understand why the initialization of pprocessor, below, is written like this:
class X
{
...
private:
boost::scoped_ptr<f_process> pprocessor_;
};
X:X()
: pprocessor_( f_process_factory<t_process>().make() ) //why the factory with template
{...}
instead of just writing
X:X()
: pprocessor_( new t_process() )
{...}
Other relevant code is:
class f_process {
...
};
class t_process : public f_process {
...
};
//
class f_process_factory_base {
public:
f_process_factory_base() { }
virtual ~f_process_factory_base() = 0 { }
virtual f_process* make() = 0;
};
template < typename processClass >
class f_process_factory : public f_process_factory_base {
public:
f_process_factory() { }
virtual ~f_process_factory() { }
virtual processClass* make() { return new processClass(); }
};
The guy who wrote the code is very clever so perhaps there is a good reason for it.
(I can't contact him to ask)
As it is, it seems kinda pointless, but I can think of a few possible uses that aren't shown here, but may be useful in the future:
Memory management: It's possible that at some point in the future the original author anticipated needing a different allocation scheme for t_process. For example, he may want to reuse old objects or allocate new ones from an arena.
Tracking creation: There may be stats collected by the f_process_factory objects when they're created. Maybe the factory can keep some static state.
Binding constructor parameters: Perhaps a specialization of the f_process_factory for t_process at some point in the future needs to pass constructor parameters to the t_process creator, but X doesn't want to know about them.
Preparing for dependency injection: It might be possible to specialize these factories to return mocks, instead of real t_process. That could be achieved in a few ways, but not exactly as written.
Specialized object creation: (This is really just the general case for the previous two), there may be specializations of t_process that get created in different circumstances - for example, it might create different t_process types based on environmental variables or operating system. This would require specializations of the factory.
If it were me, and none of these sound plausible, I'd probably rip it out, as it seems like gratuitous design pattern usage.
This look like he is using the factory design pattern to create new instances of t_process. This will allow you to delegate the responsibility of creating different types of t_process away from class X
Well, in this case it doesn't make much sense, unless the author expects the default factory's definition will be updated sometime in the future. It would make sense, though, if the factory object were passed in as a parameter; a factory gives you more flexibility in constructing an object, but if you instantiate the factory at the same place that you use it, then it really doesn't provide an advantage. So, you're right.
So, I'm learning C++, and I've run into something which I know how to do in Java, but not in C++ :).
I have a template for a container object, which is defined as such:
template <class T>
class Container {
vector<T> contained;
public:
void add(T givenObject) {
this->contained.push_back(givenObject);
}
T get(string givenIdentifier) throw (exception) {
for (int i = 0; i < this->contained.size(); i++) {
if (this->contained[i].getIdentifier() == givenIdentifier) {
return this->contained[i];
}
}
throw new exception("An error has occured which has caused the object you requested to not be found. Please report this bug.");
}
bool empty() {
return this->contained.empty();
}
bool identifierExists(string givenIdentifier) {
for (int i = 0; i < this->contained.size(); i++) {
if (this->contained[i].getIdentifier() == givenIdentifier) {
return true;
}
}
return false;
}
};
This actually works very well, with one small issue. It comes down to two lines: the first is the template definition and the second is
this->contained[i].getIdentifer()
In Java, when declaring a Generic (template) one can define a superclass/interface which all members of T must extend in order to not create an error. However, I'm not sure of a way to do this in C++, and my concern is that coupling the implementation here to a getIdentifier method which might not be defined is bad design.
Now, it's not a huge deal if that's the case, this is just a little challenge project to help me learn the language, but I like to try to do things right. Is there a way to do what I'm thinking? I know you can do it with primitives, for instance:
template <int T>
is valid, but when I try to use a user defined class, I get a compiler error. Any suggestions?
It's not possible for you to put artificial limitations on template type parameters. If the type given doesn't support the way you use it, you'll receive a compiler error. A feature called 'concepts,' which would essentially allow this, was going to be added to the next C++ standard, but it was delayed to the next-next standard due to time constraints. If T doesn't have a visible getIdentifier() function, the instantiation won't compile.
Template parameters need to be deduced at compile time. template<int T> is valid because the first template parameter is an integer; you can instantiate it with any constant integer. If you attempted to use it with a non-const integer variable, it wouldn't compile. An instance of a class isn't a compile time constant, so it can't be used.
You've gotten a couple of other answers, both quite good (especially #dauphic's, IMO). I'd just add that the code you've given really looks an awful lot like quite an inefficient imitation of an std::map. Under most circumstances, std::map will probably work better. If you look up its interface, it'll also show you a way to decouple your container from having to specify getIdentifier() directly -- instead of directly using something like getIdentifier(), it uses a comparison functor that defaults to std::less<T>, which will (in turn) use T::operator< -- but you can also specify an entirely different comparison functor if you prefer.
I should also point out that while others have pointed out that you'll get a compile error if you use getIdentifier (or whatever) and attempt to instantiate over a class that doesn't supply it. I feel obliged to warn you, however, that the error message you get may be long, convoluted, and quite difficult to decipher. This is especially likely if there's some other type that does have a getIdentifier member available. In this case the error message you get say something like "Unable to to convert from type A to type B", where type A is whatever type you used to instantiate the container, and type B is whatever (often entirely unrelated) type that happens to have a getIdentifier member. What's happening is that the compiler sees that you've used getIdentifier, and sees that type B has that, so it tries to convert your type A object to a type B object, and finds that it can't, so that's what it tells you about in the error message.
P.S. Yes, I know this is really more of a comment than an answer. I apologize for that, but it won't really fit in a comment.
You don't have to do anything. If contained[i] doesn't have a getIdentifer() function, you will get a compile-time error (just as you would using an interface contrainst in Java, and just as you would outside of using templates).
To elaborate: If you were to write,
int x = 10;
long id = x.getIdentifer();
That would be considered a "bad design". It would just be a mistake, which the compiler will catch. That is exactly what will happen in you're example.
C++ draws a pretty stark line between compile-time polymorphism (ie Templates) and run-time polymporphism (ie inheritance). So what you want to do is not supported by the language.
One typical practice to do what you are doing is to provide, in addition to T, a type that can get an identifier of a given T. This decouples the two behaviors into two types and you can specify (in English) the interface that must be implemented.
template <class T, class StringIdForT>
class Container
{
...
bool identifierExists(string givenIdentifier)
{
StringIdForT idGetter;
for (int i = 0; i < this->contained.size(); i++)
{
if (idGetter.getIdentifier(this->contained[i]) == givenIdentifier)
{
return true;
}
}
return false;
}
};
You have a similar problem, StringIdForT must still define a specified method
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.