I have a class template A
which contains a container of pointers (T*
):
template <typename T>
class A {
public:
// ...
private:
std::vector<T*> data;
};
and a bunch of functions like:
void f(const A<const T>&);
void g(const A<const T>&);
Is it OK to call these functions via a cast from A<const T>
to A<T>
?
A<double> a;
...
auto& ac = reinterpret_cast<const A<const double>&>(a);
f(ac);
I'm pretty sure that this code has undefined behaviour.
Is it dangerous to use such conversions in real life?
As A<double>
and A<const double>
are unrelated types, it's actually unspecified (originally I thought undefined) behavior and correspondingly yes it's a bad idea to use in real life: You never know what system(s) or compiler(s) you may port to that change the behavior is strange ways.
Reference:
5.2.10/11:
An lvalue expression of type T1 can be cast to the type “reference to T2” if an expression of type “pointer to T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_cast. That is, a reference cast reinterpret_cast(x) has the same effect as the conversion *reinterpret_cast(&x) with the built-in & and * operators (and similarly for reinterpret_cast(x)).
So they've redirected us to an earlier section 5.2.10/7:
An object pointer can be explicitly converted to an object pointer of a different type. ... ... Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.
If f
and g
are algorithms that work on containers, the easy solution is to change them to template algorithms that work on ranges (iterator pairs).
Although the reinterpret_cast
itself might be unspecified behaviour, attempting to access the parameters once you've done the cast is undefined behaviour.
N3337 [basic.lval]/10:
If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined— the dynamic type of the object,
— a cv-qualified version of the dynamic type of the object,
— a type similar (as defined in 4.4) to the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
— an aggregate or union type that includes one of the aforementioned types among its elements or non- static data members (including, recursively, an element or non-static data member of a subaggregate or contained union),
— a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
— a char or unsigned char type.
Your example is none of the above.
来源:https://stackoverflow.com/questions/37118426/does-reinterpret-cast-lead-to-undefined-behavior