I'm trying to use c++ iterators with interfaces, but does not manage to make it working.
I'm a bit lost with what type to choose for the vector contents. Is this need to be a pointer ? do I have to make a "new Implementation()"? In brief, it is unclear to me, and I can't manage to find useful examples about that.
Here are the interfaces and implementations (the .h file).
class Interface{
public:
virtual int method() = 0;
};
class Implementation1 : public Interface{
public:
int method();
};
class Implementation2 : public Interface{
public:
int method();
};
The .cpp file:
#include "content.h"
int Implementation1::method(){
return 1;
}
int Implementation2::method(){
return 2;
}
And my main function:
#include "content.h"
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
// create the vector and put elements in it
vector<Interface*> elements;
elements.push_back(new Implementation1());
elements.push_back(new Implementation1());
elements.push_back(new Implementation2());
// now iterate on them
vector<Interface*>::iterator iterator;
for(iterator = elements.begin(); iterator != elements.end(); ++iterator ){
*iterator->method();
}
return 1;
}
the compilator is outputting:
main.cpp: In function ‘int main()’:
main.cpp:19: error: request for member
‘method’ in ‘*
iterator.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator-> with _Iterator = Interface**, _Container = std::vector >’,
which is of non-class type
‘Interface*’
Any idea about what I'm doing wrong here ?
Change *iterator->method(); to (*iterator)->method();
The former dereferences the return of iterator->method(). Interface* doesn't have a method(), it doesn't have anything.
You want to dereference the iterator to get to your pointer, and then dereference IT.
You've basically got the same thing as Iterator** so act accordingly.
+1 for Noah about the compile error with iterator, that's a good explanation. As for your former question:
I'm a bit lost with what type to choose for the vector contents. Is this need to be a pointer ? do I have to make a "new Implementation()"?
Yes, this has to be a pointer. The reason is simple: the vector of type T stores (and owns) only elements of type T, not subtypes - and there are good reasons for that (what if the subclass had a different size?).
Therefore you have to store the objects somewhere and keep the pointers in the vector. In fact, storing them on the free store via operator new is the easiest option.
If you want your life a bit easier, you can use boost::ptr_vector for your purposes.
try (*iterator)->method();
There's nothing inherently invalid about what you've done, but creating a vector of raw pointers is typically a bad idea, you should use an ownership enforcing pointer (a "smart" pointer) like shared_ptr. And you also don't need to de-reference the iterator, it should just offer ->method() directly. However, I don't see anything directly uncompilable with this code, except possibly your *iterator->method(), cause last time I checked de-reference has a really low precedence and you may be doing *(iterator->method()) which is uncompilable.
Related
I'm trying to static_cast a unordered_set and I want to know if this is possible without undefined behavior.
Here is what I am trying to accomplish:
#include <unordered_set>
struct Base{};
struct Derived : public Base{ Derived() = default; };
int main(void){
std::unordered_set<Base *> set;
set.insert(new Derived{});
auto set_ptr{static_cast<std::unordered_set<Derived *>*>(&set)};
}
I'm trying to static_cast a set of Base * into a set of Derived *.
However this will not compile with an error:
main.cpp: In function ‘int main()’:
main.cpp:21:66: error: invalid static_cast from type ‘std::unordered_set*’ to type ‘std::unordered_set*’
auto set_ptr{static_cast<std::unordered_set<Derived *>*>(&set)};
I was wondering if there is a way to do this without entering undefined behavior territory.
In most cases you cannot perform casts with respect to the template argument, such as
MyTemplateClass<T> foo;
MyTemplateClass<U>& bar = std::static_cast<MyTemplateClass<U>&>(foo);
because types MyTemplateClass<U> and MyTemplateClass<T> are completely unrelated in terms of inheritance structure. One of the two could even be specialized to be a completely different thing!
In your case MyTemplateClass is std::unordered_set.
In case of a container of pointers, such as std::set<T*> we have a bit more knowledge of what is contained: pointers, and there are few things that could be made:
Ugly. Nonstandard. Dangerous. By standard it's undefined behavior.
Just do a reinterpret_cast<std::unorederd_set<Derived*>&>. It will work in most cases. But it is now entirely your responsibility not to break things. For example, you must make sure that there is no Base* element in the set when the std::unorederd_set<Derived*> reference is being used. It will be very easy to forget when you pass it to a function or store as a field of some object.
Clean but boilerplaty.
Write an adapter. Your own implementation of std::unordered_set<Derived*> which holds a reference to std::unordered_set<Base*> underneath and performs all the necessary casts on the way, each time you access an element.
For example, you will most likely need to write your own iterators over it. The accessor operator* will perform the static_cast or dynamic_cast to access its element. Or better yet, have the iterator stop only on elements that are in fact Derived* and skipping over all other Base*.
First, instead of static_cast, you should use dynamic_cast which:
Safely converts pointers and references to classes up, down, and
sideways along the inheritance hierarchy.
Furthermore, you cannot cast whole std::unordered_set but you need to dynamic_cast each element of your std::unordered_set like:
std::unordered_set<Derived *> second;
for (auto& it : first) {
auto derived_ptr = dynamic_cast<Derived *>(&*it);
if (nullptr != derived_ptr) {
second.insert(derived_ptr);
}
}
Please note that you need to check whether the derived_ptr is nullptr or not because, if the dynamic_cast fails, it returns the nullptr.
The code below:
#include <iostream>
#include <list>
class A
{
public:
void printHello(){std::cout << "hello";}
};
int main(int argc, char *argv)
{
std::list<A*> lista;
lista.push_back(new A());
for(std::list<A*>::iterator it=lista.begin();it!=lista.end();++it)
{
//how to get to printHello method?
//it doesn't work
it->printHello();
}
return 0;
}
This code doesn't work. My question is how to get to method 'printHello' by iterator it? Thanks.
You want
(*it)->printHello();
as the *it returns the stored pointer A* and only then you can apply ->.
Just change following line
it->printHello();
to
(*it)->printHello();
The operator*() gives access to the contained data of the container, which in your case is a pointer. When not using pointers in containers, just using operator->() would work, too.
De-referencing it will give you pointer to A, then you need to access the methods or data members.
So use :
(*it)->printHello();
Let me expand on Daniel's answer.
When you stick an asterisk in front of a variable, it is called 'dereferencing'. Used this way, the Asterisk is a 'Dereference Operator'. To put it noob-ishly (I don't know what level of understanding you have offhand), *pMyPointer acts like it was the Object that the pMyPointer was pointing to. If it was a Pointer to a Pointer, then the result is just the Pointer.
As an example, when you call a method on a pointer, you use the Into Operator ->.
These two often do the same thing:
pMyPointer->MyFunction();
(*pMyPointer).MyFunction();
In the case of the C++ iterators, the Dereference Operator is overwritten to return the object stored in its position. In this case, what is stored in its position is a pointer, so you still have to use -> unless you stick another Dereference Operator in there.
So I go this:
class A;
class B : public A;
class C : public B;
vector<A*> *vecA;
vector<C*> *vecC;
And I want to cast a vectC into a vecA.
vector<A*> *_newA = static_cast< vector<A*>* >(vecC); //gives an error
So I used void pointer as a buffer and the cast:
void *buffer = vecC;
vector<A*> *_newA = static_cast< vector<A*>* >(buffer); //works
Is this valid? Is there another way to do it?
You should just have a std::vector<A*> and then when you wish to put a B or C inside, you can do this:
std::vector<A*> vec;
vec.push_back(b);
This will work much better than anything you're currently doing.
Also, you should use std::unique_ptr or std::shared_ptr, depending on ownership semantics of your pointers. Owning raw pointers are a no-no!!
Is this valid?
No it's not. It is completely undefined what happens if you access it.
Is there another way to do it?
Yes. It depends on what you want to do:
copy the content: std::copy(vecC.begin(), vecC.end(), std::back_inserter(vecA));
create an adaptor which behaves as random access container of A* if given a container or iterator of C* or any other derived type
I am sure there are other solutions, just tell us what you want to do
The magic words you probably needed to know are "covariance" and "contravariance". Have a look here for a very closely related issue.
Short answer: there's no neat, sensible way to do the conversion you want to do merely with casts. You will need to copy to contents of your old vector the long way into your new vector.
But more importantly: 1. Don't ever use new on a standard container type. 2. Don't pass around pointers to standard container types. 3. Don't pass around raw pointers to your own objects, use std::shared_ptr instead.
Instead of detouring via void*, with C++11 just use reinterpret_cast.
However, the conversion that you desire permits very ungood things:
#include <iostream>
#include <vector>
using namespace std;
class Base {};
class Derived: public Base
{ public: int x; Derived(): x(42) {} };
int main()
{
vector< Derived* > v;
Derived d;
v.push_back( &d );
cout << v.back()->x << endl; // 42
vector< Base* >* pbv =
reinterpret_cast< vector< Base* >* >( &v );
Base b;
pbv->push_back( &b );
cout << v.back()->x << endl; // indeterminate value
}
It's roughly the same issue that you have with converting T** to T const** (not permitted, could allow ungood things). The short of it is, don't do this unless you know exactly what you're doing. The longer of it, hm, well, there's not room to discuss it here, but it involves differentiating between mutable and immutable collections, and being very very careful.
edit: as others (who did not address the conversion question) have already stated, a practical solution is a vector of A pointers, or smart pointers, and then using C++ polymorphism (i.e. virtual member functions).
It looks to me as if you're looking for covariant support for generic (template) types. This is not supported at all by C++. It is supported by the CLR - and C#/VB - though only in the latest versions.
In spite of this, to echo others' responses, you're likely barking up the wrong tree. My hunch is that you want to have a vector of pointers to A-typed objects... and this type should include virtual methods and a virtual destructor - as necessary. It's impossible to be more specific about a suitable alternative approach without a better understanding of the high-level problem you're trying to solve - which is not evident from your question.
Is it legal to have a vector of references to objects, like the following?
vector<Agent&> seenAgents;
Which would for example be populated by some, but not all of the objects in the scene?
I have a vector of Agent objects, but the vector outlined above should hold references to only the ones each agent can currently see - meaning that the references will be being added and removed all the time.
Is this something the language will allow? And in addition, is there anything else I need to be aware of? If I remove a reference from the vector does it persist anywhere? Is it a memory leak?
I seem to be getting this error on the line declaring the vector:
error C2528: 'pointer' : pointer to reference is illegal
Is this something directly to do with the line or is it most likely occurring somewhere else? It's being initialised in the constructors initialiser list like this:
seenAgents(vector<Agents&>())
You can't have vector of references, as a reference is not copyable assignable and all STL containers are supposed to store copyable assignable items.
But you can make the container to hold pointers. Like this:
vector< Agents* > seenAgents;
This is a little dangerous. You need to be sure that these pointers will remain valid. I mean - if someone deletes an object, pointed by a pointer in this container, the pointer becomes invalid. You need to be sure that this will not happen, because you can't check it (you can't check for NULL, because a pointer will not become NULL, if someone deletes the pointed object).
The best solution here (provided by container with pointers) would be to use some smart pointers - some with reference count, for example; they will guarantee you that the object will exist and that the pointer is valid. And in case that the object, pointed by the smart pointer, is destroyed, you can check it for NULL.
You can use std::reference_wrapper instead in C++11:
std::reference_wrapper is a class template that wraps a reference in a copyable, assignable object. It is frequently used as a mechanism to store references inside standard containers (like std::vector) which cannot normally hold references.
Example:
#include <functional>
#include <vector>
#include <iostream>
int main(int argc, char *argv[])
{
int a = 5;
int b = 6;
std::vector<std::reference_wrapper<const int>> v;
v.push_back(a);
v.push_back(b);
for (const auto& vi: v)
{
std::cout << vi << std::endl;
}
return 0;
}
https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
You can't do it. Use pointers.
The Boost library provides PTR_VECTOR which is a better solution than:
vector<T*> foo;
I wanted similar functionality. In the end, here is what I did:
template <class T> class VectorOfRefs : public std::vector<T *> {
public:
inline T & at( const uint64_t i ) {
T * x = std::vector<T *>::at( i );
return *x;
}
};
VectorOfRefs < MyType > myVector;
myVector.push_back( &myInstance0 );
myVector.push_back( &myInstance1 );
// later in the code:
myVector.at( i ).myMethod();
Obviously this is a vector of pointers underneath the covers.
Normally I would use STL and settle for myVector.at( i )->myMethod(), but I wanted to use the ++ operator, so I had the following two options:
// using STL:
(*myVector.at(i))++;
// or, using my wrapper:
myVector.at( i )++;
I find the notation with the wrapper far preferable in terms of code readability. I don't like the wrapper, per se, but it pays dividends later.
Is there a way to avoid copying large vectors, when a function expects a vector with (pointer to) baseclass objects as input but I only have a vector of (pointers to) derived objects?
class Base {};
class Derived : public Base {};
void doStuff(vector<Base*> &vec)
{
//do stuff with vec objects
}
int main()
{
vector<Derived*> fooDerived(1000000);
vector<Base*> fooBase(fooDerived.begin(), fooDerived.end()); // how to avoid copying here?
doStuff(fooBase);
}
If you could use a vector<Derived*> as if it where a vector<Base*>, you could add a pointer to a class OtherDerived : public Base to that vector. This would be dangerous.
You can't cast the vectors. However, you shouldn't really need to either.
If you really want, you could use Boost Iterator (documentation)
static Derived* ToDerived(Base* b)
{
return dynamic_cast<Derived*>(b); // return null for incompatible subtypes
}
static void DoSomething(Derived* d)
{
if (!d)
return; // incompatible type or null entry
// do work
}
// somewhere:
{
std::vector<Base*> bases;
std::for_each(
boost::make_transform_iterator(bases.begin(), &ToDerived),
boost::make_transform_iterator(bases.end(), &ToDerived),
DoSomething);
}
Note: a particularly handy effect of using dynamic_cast<Derived*> is that if the runtime type of the object cannot be casted to Derived* (e.g. because it is actually an OtherDerived*, it will simply return a null pointer.
If your definition of doStuff() is absolutely mandatory, then you won't get around the copy. Containers of pointers aren't "covariant" with respect to the pointee's class hierarchy, for a whole host of reasons. (For example, if you could treat vector<Derived*> like a vector<Base*>, you could insert Base-pointers into it which wouldn't behave like Derived-pointers. In any event, the parameter type of a container is fixed and part of the container's type.)
If you do have some leeway with the function, you could restructure the code a bit: You could make it a template parametrized on the container, or a template on an iterator range, and/or you could split the actual workload into a separate function. For example:
void doStuffImpl(Base *);
template <typename Iter>
void doStuff(Iter begin, Iter end)
{
for (Iter it = begin; it != end; ++it)
{
doStuffImpl(*it); // conversion happens here
}
}
Since your template for the vector is a pointer, your fooBase local variable is going to be using reference. Maybe the question is not very clear, if you could specify clearly we may try to address the problem!
One way is to store only pointers to the base class like this:
vector<Base*> v(100);
v.push_back(new Derived());
doStuff(v);
I found this topic interesting where they mention you can safely cast Derived* to Base* (but not the other side) while this is not possible from vector<Derived*> to vector<Base*> but you kind of should be able to... (Ok, the address of the vector changes, thus needing a copy)
One dirty solution they mention is using reinterpret_cast<vector<Base*> >(vector<Derived*>) but not sure if it's better then using the copy constructor... probably the same thing happens.