Search code examples
c++most-vexing-parse

Inheriting from std::vector, compiler error? (most vexing parse)


For people who see this question: Take a look at the answer and consider using: cdecl

Why does the code below give a compiler error:

prog.cpp: In function ‘int main()’:
prog.cpp:23:4: error: request for member ‘size’ in ‘a’, which is of non-class type ‘RangeVec<int>(RangeVec<int>)’
  a.size();
    ^

I don't understand what's wrong with this code?

#include <iostream>
#include <vector>

template<typename Type>
class RangeVec: public std::vector<Type> {
    public:

        RangeVec( const RangeVec & v): std::vector<Type>(v){}
        RangeVec( const RangeVec && v): std::vector<Type>(std::move(v)) {}

        RangeVec( const std::vector<Type> &v)
            : std::vector<Type>(v)
        {
            //std::sort(std::vector<Type>::begin(),std::vector<Type>::end());
        }
};

int main(){
    std::vector<int> v;
    RangeVec<int> b(v);
    RangeVec<int> a(  RangeVec<int>(b) );
    a.size(); // b.size() works ???? why??
}

Solution

  •  RangeVec<int> a(  RangeVec<int>(b) );
    

    This is a declaration of a function a that returns a RangeVec<int> and takes one argument called b of type RangeVec<int>. This is the most vexing parse. You can fix it with C++11's uniform initialization syntax:

     RangeVec<int> a{RangeVec<int>{b}};
    

    Or if you don't have a C++11 compiler, just introduce an extra pair of parantheses:

     RangeVec<int> a((RangeVec<int>(b)))
    

    Note also that deriving from standard containers is usually a bad idea.