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.
Related
I am trying to call a child function from a parent instance using explicit down-casting (thanks for pointing out #Aconcagua). As a beginner in C++, I have something like this:
Road currentRoad = ...;
duration = ((SpeedDataRoad) currentRoad).getSpeedProfileTime(dateinMillis, isRightDirection);
class SpeedDataRoad inherits from Road:
class SpeedDataRoad : public Road{
double getSpeedProfileTime(long dateinMillis, bool isRightDirection) {
...
}
However I am getting the error:
No matching conversion for C-style cast from 'Road' to 'SpeedDataRoad'
Any suggestions on what I am doing wrong would be appreciated.
Just to be clear, what I am trying to achieve in Java would be written like this and working correctly:
duration = ((SpeedDataRoad) currentRoad).getSpeedProfileTime(currentTime, isRightDirection);
You suffer from an effect called 'object slicing':
SpeedDataRoad sdr;
Road currentRoad = sdr;
At the second line, sdr is assigned by value to currentRoad, but the latter is not of appropriate type to hold a complete SpeedDataRoad object. So all surplus pieces of SpeedDataRoad are simply cut away and all that remains is a pure Road object only containing the Road parts of original sdr object.
At the same time, as you only have a pure Road object left, you cannot cast it back to SpeedDataRoad object. From where should the now missing parts come from?
This is exactly the same reason why you cannot place polymorphic types directly into a container (like std::vector) of the base class.
What you need are either pointers (if you want to be able to re-assign) or references (to be preferred otherwise):
SpeedDataRoad sdr;
Road& currentRoad = sdr;
// ^ (!)
// or:
Road* currentRoad = &sdr;
Now you can do the cast. But explicit down-casts have a smell of bad design. You might be better off with a polymorphic approach right from the start:
class Road
{
public:
virtual double getSpeedProfileTime(long, bool) = 0;
// ^ pure virtual
// alternatively, you can provide a default implementation
};
class SpeedDataRoad : public Road
{
public:
double getSpeedProfileTime(long, bool) override
{ /* ... */ }
};
Now you can simply have:
SpeedDataRoad sdr;
Road& currentRoad = sdr;
double profile = currentRoad.getSpeedProfileTime(0, false);
As being virtual, you'll always get the right variant of the function, no matter which sub-class we have at all and in which way it might override the function...
Side note 1: Instead of old C-style casts, you might prefer the more modern C++ casts, you can control more fine grained what you actually want to do:
Road* someRoad = ...;
SpeedDataRoad* sdr = static_cast<SpeedDataRoad*>(someRoad);
SpeedDataRoad* sdr = dynamic_cast<SpeedDataRoad*>(someRoad);
You would use a static_cast, if you are 100% sure that the object only can be of desired type. You avoid any run-time tests that wouldn't serve anything at all in this situation (you are 100% sure anyway, remember?). Curiously recurring template pattern is a typical scenario for.
If you cannot be sure about the type, then dynamic_cast comes into play, it will do some run-time type checking and just return a null pointer (if used on pointers) or throw a std::bad_cast (if used on references), if the actual type is not of desired type (or a sub class of). Such a scenario can arise when different polymorphic types are stored in a vector (as pointers to base class, see above). But again: Needing a cast at all might be a hint to your design being flawed...
(For completeness: There are yet const_cast and reinterpret_cast, but you should stay away from these unless/until you really, really know what you do.)
Side note 2: Differences to Java.
In Java, we differentiate implicitly between native and reference types. Native ones are always passed by value, reference types always by reference – well, Java reference, which actually resembles far more a C++ pointer (can be null, can be re-assigned) than a C++ reference. In Java, this happens implicitly, in C++, you need to be explicit about (on the other hand, you can have both behaviours for any type).
Java cast on (Java!) reference behaves like C++ dynamic_cast (on reference, i. e. throws, it won't return null on type mismatch).
Finally (concerning my polymorphism recommendation), in Java all functions are implicitly virtual, in C++, you again have to be explicit about (apply the virtual keyword, see above).
You are slicing your SpeedDataRoad object. Unlike Java objects, which have pointer/reference semantics, C++ objects have value semantics. That means, in your example, currentRoad is a Road, not a SpeedDataRoad. It is a copy of the Road part of whatever SppedDataRoad is created in your ....
To work with polymorphism is C++ you need to use references or pointers. That is, the following will not work because currentRoad is not a SpeedDataRoad:
double foo(Road currentRoad)
{
//...
return ((SpeedDataRoad)currentRoad).getSpeedProfileTime(currentTime, isRightDirection);
}
int main()
{
SpeedDataRoad road;
foo(road);
}
While the following will work because currentRoad references a SpeedDataRoad:
double foo(Road& currentRoad)
// ^---------------- Pass by reference now
{
//...
return dynamic_cast<SpeedDataRoad&>(currentRoad).getSpeedProfileTime(currentTime, isRightDirection);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Using C++-style cast and casting reference to reference
}
int main()
{
SpeedDataRoad road;
foo(road);
}
In the first example, currentRoad is a copy of the Road part of road, while in the second example currentRoad is a reference to road.
You should also avoid C-style casts in C++. In this instance, it would be better to use dynamic_cast<SpeedDataRoad&>(currentRoad) or, if you're absolutely sure currentRoad will always be a reference to a SpeedDataRoad object, static_cast<SpeedDataRoad&>(currentRoad). The former will do runtime type checking and throw an exception if currentRoad isn't a reference to a SpeedDataRoad while the latter will avoid the (small) overhead of doing runtime type checking, but will result in undefined behavior if currentRoad isn't a reference to a SpeedDataRoad.
That's called a downcast and not an upcast - the straightforward way to this by a dynamic_cast:
if (SpeedDataRoad* sdroad = dynamic_cast<SpeedDataRoad*>(¤tRoad); sdroad != nullptr) {
duration = sdroad->getSpeedProfileTime(currentTime, isRightDirection);
}
If you want to check inside a function if you can downcast a pointer/refernce into a child, you need to use dynamic cast.
void foo(Road* road){
SpeedDataRoad* child{nullptr};
if(child = dynamic_cast<SpeedDaraRoad*>(road){
// Do something with SpeedDataRoad
} else {
// road is not an instance of SpeedDataRoad
}
}
You can also use dynamic_cast with references, like so
cppSpeedDataRoad& child = dynamic_cast<SpeedDataRoad&>(reference_to_road);
But be carefull, as if the cast fails, std::bad_cast will be throw.
In C++, we try not to use C-style casting. (typename)object.
Instead, there are 4 types of type-casting.
static_cast<typename*>(pointer) static_cast<typename>(value): Upcasting of pointers and type-casting for value types
dynamic_cast<typename*>(pointer): Safe-downcasting of pointers (the one you should use). It does a runtime check for upcasting, hence, there is runtime cost.
const_cast<...>(...): Constant type
reinterpret_cast<typename*>(pointer) reinterpret_cast<typename>(value): Similar to C-style cast.
For objects (stack allocated), I rarely use casting. Because naturally objects in C++ has their own size, casting may change their size.
I want to write a function which takes as an argument an object from the class "Armor", however, when I call the function, I use instead an object from the base class "Item". Of course this object I use, even though may only be considered an "Item", may also be an "Armor". Only when I am sure it is an "Armor", I want to call the function.
In my case, I store items in a vector (these items can be armors). I want to get this item from the vector and call the function with it (equip the item, which I know is an armor).
class Item{
};
class Armor : public Item{
};
void equipArmor(Armor armor){ //Armor class argument
//Equip the armor
}
int main(){
vector<Item> items;
Armor a;
items.push_back(a);
equipArmor(items[0]); //Call function with an "Item" as an argument (even though it is in fact also an "Armor")
}
The problem
You have a vector of Item. When you push_back an Armor it will be sliced into an Item. So in the vector you have no longer an Armor but just an ordinary Item.
This is why your code won't work. First you cannot call your equipArmor() function with an Item, since it expects an Armor and downcasting is never implicit. But even if you could, you would always pass an Item value and never an Armor value.
The solution
To solve your issue, you need to work with pointers (better smart pointers) or references.
The first thing you will need to be able to work with polymorphic types and doing runtime type determination, is to have at least one virtual function in your base class:
class Item{
public:
virtual ~Item() {}
};
Now let's make your vector a vector of shared pointers. The nice thing is that those will ensure that objects will be destroyed when they are no longer used in any shared pointer. So less hassle with memory management, and less hassle with the rule of 3 :
vector<shared_ptr<Item>> items;
shared_ptr<Item> a = make_shared<Armor>();
items.push_back(a);
shared_ptr<Item> i = make_shared<Item>();
items.push_back(i);
equipArmor(items[0]); // lets just try the two possible cases
equipArmor(items[1]);
Finally, in your function, you can then sense for the real type and act accordingly, in a safe manner using dynamic_pointer_cast:
void equipArmor(shared_ptr<Item> item){ //Armor class argument
shared_ptr<Armor> a = dynamic_pointer_cast<Armor>(item);
if (a) {
cout << "Armor"<<endl;
}
else cout << "Item"<<endl;
}
Online demo
Remarks
If your type is not polymorphic, you cannot you dynamic_pointer_cast. You still could cast with a static_pointer_cast, but this is risky, because it requires you to know for sure that the casted smart pointer has the right type.
If you prefer raw pointers, you the same principles would apply, but yo'ud use dynamic_cast or static_cast respectively. But again, static_cast requires you to be absolutely sure of the type. And how can you be, if you have a vector full of random items ?
You want to cast from the base class (Item) to the subclass (Armor). This is impossible.
You could do this if items would be a vector of pointers to Items. You can then cast an Item * to an Armor * if you are sure that the underlying object is actually an Armour.
int main(){
std::vector<Item *> items;
Armor a;
items.push_back(&a);
// This only works if items[0] points to an Armor object
equipArmor(*static_cast<Armor *>(items[0]));
}
I have two classes, A, and B. A is a parent class of B, and I have a function that takes in a pointer to a class of type A, checks if it is also of type B, and if so will call another function that takes in a pointer to a class of type B.
When the function calls the other function, I supply reinterpret_cast(a) as the parameter. If this seems ambiguous here is a code example:
void abc(A * a) {
if (a->IsA("B")) { //please dont worry much about this line,
//my real concern is the reinterpret_cast
def(reinterpret_cast<B *>(a));
};
};
So now that you know how I am calling "def", I am wondering if reinterpret_cast actually returns a pointer of type B to be sent off as the parameter to def.
I would appreciate any help.
Thanks
reinterpret_cast will always do what you say - it is a sledghammer. You can do
def(reinterpret_cast<B *>(42));
or
std::string hw = "hello";
def(reinterpret_cast<B *>(hw));
it will always return a pointer that might point at the correct type. It assumes you know what you are doing
You will have a pointer of type B*, but reinterpret_cast isn't really great.
If you're sure the type is a B, use static_cast, if not, use dynamic_cast and test the pointer (if dynamic_cast fails, it returns nullptr)
See https://stackoverflow.com/a/332086/5303336
reinterpret_cast is the result of a broken type system. Its behaviour assumes that there is a union such as
union {
TypeA anA;
TypeB aB;
} a;
so
reinterpret_cast< B* >( a );
Assumes a is pointer to member anA and can then deliver the aB address.
If the type is part of the same class hierarchy, then static_cast<> would allow you to find out at compile time if there was enough information to perform the cast. This is generally when B is a base class of A (either singly or multiply).
If there is insufficient information for static_cast to work, then it may be possible to get a dynamic_cast<> to work. This is the case where the B type is derived in some way from A.
It is important to note that the dynamic_cast<B*>( a ) or static_cast< B*>( a ) may not yield the same address when they succeed.
That is because when multiply inherited, the secondary inheritance creates multiple classes and vtables in the object. When this happens, the static_cast, dynamic_cast adjust the base address of the object to find the correct embedded class base address.
The fact that dynamic_cast and static_cast may change the address, is why reinterpret_cast is discouraged. It can result in a value which doesn't do what you want.
Reinterpret cast will always return a pointer. It may just not be a valid pointer in the sense that it actually points to an object of type B.
If B has more than one base class, and A is not the first base class, reinterpret cast will do the wrong thing and fail to perform necessary adjustment to the pointer.
For your usecase you should use a static cast which has the advantage that the compiler will check whether B is actually derived from A and perform any needed adjustment. No runtime overhead is incurred by additional checks, however there will be no warning if the object is not actually of type B and the program will fail arbitrarily.
As others have stated, reinterpret_cast is the wrong solution, use dynamic_cast instead:
void abc(A * a) {
B *b = dynamic_cast<B*>(a);
if (b) {
def(b);
}
}
I've been programming C++ for a while now and I'm starting to doubt that the rule use references whenever possible should be applied everywhere.
Unlike this related SO post I'm interested in a different kind of thing.
In my experience the reference/pointer mix messes up your code:
std::vector<Foo *> &x = get_from_somewhere(); // OK? reference as return value
some_func_pass_by_ref(x); // OK reference argument and reference variable
some_func_by_pointer(x[4]); // OK pointer arg, pointer value
some_func_pass_elem_by_ref(*x[5]); // BAD: pointer value, reference argument
some_func_that_requires_vec_ptr(&x); // BAD: reference value, pointer argument
One option would be to replace & with * const like Foo & with Foo * const
void some_func_by_ref(const std::vector<Foo * const> * const); // BAD: verbose!
this way at least the traversals are gone. and me rewriting function headers is gone, because all arguments will be pointers... at the price of polluting the code with const instead of pointer arithmetic (mainly & and *).
I would like to know how and when you apply use references whenever possible rule.
considering:
minimal rewriting of function prototypes (i.e.: oh damn I need need to rewrite alot of prototypes because I want to put this referenced element into a container)
increasing readability
avoid application of * to transform Foo* to Foo& and vice versa
avoid excessive const usage as in * const
NOTES: one thing I figured is to use pointers whenever I intend to ever put the element into an STL container (see boost::ref)
I don't think this is something C++03 specific but C++11 solutions are fine if they can be backported to C++03 (i.e.: NRVO instead of move-semantics).
When should I use references in C++?
When you need to treat a variable like the object itself (most cases when you don't explicitly need pointers and don't want to take ownership of an object).
I would like to know how and when you apply use references whenever possible rule.
whenever possible, except when you need to:
work on the address (log the address, diagnose or write custom memory allocation, etc)
take ownership of parameter (pass by value)
respect an interface that requires a pointer (C interoperability code and legacy code).
Bjarne Stroustrup stated in his book that he introduced references to the language because operators needed to be called without making a copy of the object (that would mean "by pointer") and he needed to respect syntax similar to calling by value (that would mean "not by pointer") (and thus references were born).
In short, you should use pointers as little as possible:
if the value is optional ("can be null") then use a std::optional around it, not a pointer
if you need to take ownership of the value, receive parameter by value (not a pointer)
if you need to read a value without modifying it, receive parameter by const &
if you need to allocate dynamically or return newly/dynamically allocated object, transmit value by one of: std::shared_ptr, std::unique_ptr, your_raii_pointer_class_here - not by (raw) pointer
if you need to pass a pointer to C code, you should still use the std::xxx_ptr classes, and get the pointer using .get() for getting the raw pointer.
one thing I figured is to use pointers whenever I intend to ever put the element into an STL container (or can I get rid of this?)
You can use Boost Pointer Container library.
IMHO the rule stands because raw pointers are dangerous because ownership and destruction responsibility becomes rapidly unclear. Hence the multiple encapsulations around the concept (smart_ptr, auto_ptr, unique_ptr, ...).
First, consider using such encapsulations instead of raw pointer in your container.
Second, why do you need to put pointers in a container ? I mean, they're meant to contain full objects ; they have an allocator as template argument for precise memory allocation after all. Most of the time, you want pointers because you have an OO-approach making heavy use of polymorphism. You should reconsider this approach. For example you can replace:
struct Animal {virtual std::string operator()() = 0;};
struct Dog : Animal {std::string operator()() {return "woof";}};
struct Cat : Animal {std::string operator()() {return "miaow";}};
// can not have a vector<Animal>
By something like this, using Boost.Variant :
struct Dog {std::string operator()() {return "woof";}};
struct Cat {std::string operator()() {return "miaow";}};
typedef boost::variant<Dog, Cat> Animal;
// can have a vector<Animal>
This way when you add a new animal, you inherit nothing, you just add it to the variant.
You can also consider, a little bit more complicated, but far more generic, using Boost.Fusion :
struct Dog {std::string talk; Dog() : talk("wook"){}};
struct Cat {std::string talk; Cat() : talk("miaow"){}};
BOOST_FUSION_ADAPT_STRUCT(Dog, (std::string, talk))
BOOST_FUSION_ADAPT_STRUCT(Cat, (std::string, talk))
typedef boost::fusion::vector<std::string> Animal;
int main()
{
vector<Animal> animals;
animals.push_back(Dog());
animals.push_back(Cat());
using boost::fusion::at;
using boost::mpl::int_;
for(auto a : animals)
{
cout << at<int_<0>>(a) << endl;
}
}
This way you do not even modify an aggregate like variant nor the algorithms on animals, you just need to provide a FUSION_ADAPT matching the used algorithms prerequisites. Both versions (variant and fusion) let you define orthogonal object groups, a useful thing you can not do with inheritance trees.
The following ways seem reasonable dealing with this:
boost and C++11 have a class that can cheaply be used to store references in a container: Reference Wrapper
A good advice is to use the handle/body idiom more often instead of passing around raw pointers. This also solves the ownership issue of the memory that is governed by the reference or the pointer. Sean Parent from Adobe has pointed this out at a talk at going native 2013.
I chose to use the Handle/Body Idiom approach because it gives pointers automatically copy/assign behaviour while hiding the underlying implementation and ownership semantics. It also acts as kind of a compile time firewall reducing header file inclusion.
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.