1
votes

I am able to typecast reference of vector<void*> to reference of vector<Foo*> whereas I am unable to typecast vector<void*> to vector<Foo*>. I am getting the error C2440: 'reinterpret_cast' : cannot convert from 'std::vector<_Ty>' to 'std::vector<_Ty>' why?

And I am able to typecast void* to Foo* without getting compiler error.

void* g =&foo;
reportFooVector2(reinterpret_cast<Foo*>(g));

Below is my entire code.

#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;

struct Foo
{
  string s;
  int i;
};


void reportFooVector( vector <Foo*> * pvf )
{

}


void reportFooVector1( vector <Foo*> pvf )
{
}

void reportFooVector2( Foo *pvf )
{
}


int main()
{
    struct Foo foo = {"foo",  5};
    struct Foo goo = {"goo", 10};
    void* g =&foo;
    reportFooVector2(reinterpret_cast<Foo*>(g));
    vector <void *> vf;
    vf.push_back(&foo);
    vf.push_back(&goo);
    reportFooVector1( reinterpret_cast< vector < Foo * >  >(vf));
    reportFooVector( reinterpret_cast< vector < Foo * > * >(&vf));
}

In the above program I am getting the compiler error C2440: 'reinterpret_cast' : cannot convert from 'std::vector<_Ty>' to 'std::vector<_Ty>' when calling the line reportFooVector1( reinterpret_cast< vector < Foo * > >(vf));

Could you please anyone tell the reason for it?

1
the is an exception for void* that says it is allowed to be cast to and from any other pointer type. There is no such exception for std::vector<void*> - 463035818_is_not_a_number
The reason is that it's not allowed in C++. An lvalue expression can only be reintepret_cast-ed to a reference to a type, unless the lvalue expression is a pointer, an integer, and enumeration, etc... Since a vector is neither, the only thing a vector can be reinterpret_casted is a reference. - Sam Varshavchik
Those are pointers, not references. Not a nitpick, since C++ has actual references and those are distinct types from pointers. Best to get terms correct to avoid confusion. - StoryTeller - Unslander Monica
@SamVarshavchik seems a perfect answer to me, why post it in a comment ? - darune
Why are you storing a vector of void* pointers in the first place? - Paul Belanger

1 Answers

0
votes

First at a high level what does reinterpret_cast do?

  • Converts any pointer type to any other pointer type, even of unrelated classes
  • Cast pointers to or from integer types

Note that everything done here involves casting between, to, or from pointer types. So it's important to note that reinterpret_cast<vector<Foo*>>(vf) is not valid, as it casts a vector<void*> to a vector<Foo*>. All though these are vectors that contain pointers, neither vf nor vector<Foo*> is itself a pointer.

Having addressed this lets discuss reinterpret_cast<vector<Foo*>*>(&vf) this is also will result in undefined behavior if it is dereferenced because of the rules on Type Aliasing.
Given that the input to the reinterpret_cast is DynamicType and the output is AliasedType the reinterpret_cast is valid only if:

  • AliasedType and DynamicType are similar
  • AliasedType is the (possibly cv-qualified) signed or unsigned variant of DynamicType
  • AliasedType is std::byte, char, or unsigned char: this permits examination of the object representation of any object as an array of bytes

Informally, two types are similar if, ignoring top-level cv-qualification:

  • They are the same type
  • They are both pointers, and the pointed-to types are similar
  • They are both pointers to member of the same class, and the types of the pointed-to members are similar
  • They are both arrays of the same size or both arrays of unknown bound, and the array element types are similar

Since none of these are true with respect to vector<void*>* and vector<Foo*>* dereferencing the output of this reinterpret_cast is undefined behavior.


Now that we've discussed why these are both undesirable; let me suggest that you instead do: void reportFooVector(void** pvf, const size_t count) You can call this by doing: reportFooVector(data(vf), size(vf)) Internally to reportFooVector you'd need to cast individual elements to Foo*s in order to operate on them.