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!
You are accessing the value_type trough the variable instance and not the variable type.
Method 1 – this works:
Method 2 – or this:
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:this resolves to the following C++ code:
and ultimately what is resolved first is the
SVector<double, 2>::Dim()part. This would force the vector instance declared trough variablevto have a templatized inner class named SVector. And because this does not happen this results in error:STL
vectorwould 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.