tags:

views:

1251

answers:

1

Hi, I'm trying to get my head around why the following doesn't work. I have a std::vector and I want to call a static member function of it's contained value_type like so:

std::vector<Vector> v;
unsigned u = v.value_type::Dim();

where Vector is in fact a typedef for a templated type:

template <typename T, unsigned U> class SVector; 
typedef SVector<double, 2> Vector; //two-dimensional SVector containing doubles

and the static member function Dim() actually inlines the dimensionality U of the Vector.

Now the compiler returns an error message saying:

 error: ‘SVector<double, 2u>’ is not a base of 
 ‘std::vector<SVector<double, 2u>, std::allocator<SVector<double, 2u> > >

which puzzles me. I can replace the apparently offending line by

unsigned u = Vector::Dim();

and that works, but is obviously ugly as it hardcodes assumptions about the value_type of v... Thanks!

+15  A: 

You are accessing the value_type trough the variable instance and not the variable type.

Method 1 - this works:

typedef std::vector<Vector> MyVector;
MyVector v;
unsigned u = MyVector::value_type::Dim();

Method 2 - or this:

std::vector<Vector> v;
unsigned u = std::vector<Vector>::value_type::Dim();

If you typedef like on method 1 you do not hardcode assumptions on vector template parameter and you write clean code.


Edit: Expanded to explain the behavior for this issue as requested by question owner:

The scope resolution operator :: has higher precedence than any other C++ operator. This includes the Member access from an object . operator. Thus when you write something like:

unsigned u= v.value_type::Dim();

this resolves to the following C++ code:

unsigned u = v.SVector<double, 2>::Dim();

and ultimately what is resolved first is the SVector<double, 2>::Dim() part. This would force the vector instance declared trough variable v to have a templatized inner class named SVector. And because this does not happen this results in error:

error C2039: 'SVector<double,2>' : is not a member of 'std::vector<_Ty>'

STL vector would have to be "expanded" for each usage of this pattern (accessing value_type trough variable instance and not variable type). This is not a good solution as it leads to lots of boilerplate and unnecessary and unmaintainable code. By following the above mentioned solutions you avoid all this and can easily do what you wanted.

smink
Many thanks, that's great. I didn't know it was not allowed to access the value_type through the instance. Would you by any chance know why this is not allowed (what would go wrong if it was allowed)?
yungchin
@yungchin check if the explanation that I just added is clear enough about this issue.
smink
nothing would go wrong if it was allowed - since C++ is statically typed it already knows v is a std::vector<Vector>, but then again YOU already know what v is too, so it makes no difference really. I'm guessing the C++ designers wanted clear separation between static members and instance members.
Greg Rogers
I agree with you Greg.
smink
@Greg and smink: awesome, thanks. It's completely clear to me now.
yungchin