mjdn mjdn - 1 month ago 36
C++ Question

No Matching Constructor for Initialization on Mac

I am learning c++ from Programming: Principles and Practice Using C++ / Edition 2 and I've run into a problem with vectors. I'm using the included header file provided from Stroustrup's book here. When I compile the following vector program, I get an error.

#include "std_lib_facilities.h"

int main()
{
vector<int> v = {5, 7, 9, 4, 6, 8};
for (int i=0; i<v.size(); ++i)
cout << v[i] << endl;
}


Error

vector.cpp:5:21 error: no matching constructor for initialization of 'Vector<int>'
vector<int> v = {5, 7, 9, 4, 6, 8};
^ ~~~~~~~~~~~~~~~~~~
./std_lib_facilities.h:82:5: note: candidate constructor template not viable:
requires 2 arguments, but 6 were provided
Vector(I first, I last) :std::vector<T>(first, last) {}
^
./std_lib_facilities.h:79:14: note: candidate constructor not viable: requires 2
arguments but 6 were provided
Vector(size_type n, const T& v) :std::vector<T>(n,v) {}
^
./std_lib_facilities.h:79:14: note: candidate constructor not viable: requires
single argument 'n', but 6 arguments were provided
explicit Vector(size_type n) :std::vector<T>(n) {}
./std_lib_facilities.h:75:27: note: candidate constructor (the implicit move
constructor) not viable: requires 1 argument, but 6 were provided
template< class T> struct Vector : public std::vector<T> {
^
./std_lib_facilities.h:75:27: note: candidate constructor (the implicit copy
constructor) not viable: requires 1 argument but 6 were provided
./std_lib_facilities.h:78:5: note: candidate constructor not viable: requires 0
arguments, but 6 were provided
Vector() { }
^


I'm compiling with: clang++ -std=c++11 -stdlib=libc++ vector.cpp

When I check my version of Clang, I get:

Apple LLVM Version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin16.1.0
Thread model: posse
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin


I am having trouble making sense of the error and warnings and not sure where to go from here. Thank you for any insight you may provide.

Answer

std_lib_facilities.h defines class Vector<T> as:

template< class T> struct Vector : public std::vector<T> {
    typedef typename std::vector<T>::size_type size_type;

    Vector() { }
    explicit Vector(size_type n) :std::vector<T>(n) {}
    Vector(size_type n, const T& v) :std::vector<T>(n,v) {}
    template <class I>
    Vector(I first, I last) :std::vector<T>(first,last) {}

    T& operator[](unsigned int i) // rather than return at(i);
    {
        if (i<0||this->size()<=i) throw Range_error(i);
        return std::vector<T>::operator[](i);
    }
    const T& operator[](unsigned int i) const
    {
        if (i<0||this->size()<=i) throw Range_error(i);
        return std::vector<T>::operator[](i);
    }
};

// disgusting macro hack to get a range checked vector:
#define vector Vector

As you can see, there's no initializer_list constructor.

At this point, your options are limited.

  1. You can eschew using std_lib_facilities.h
  2. You can #undef vector after including std_lib_facilities.h
  3. You can replace Vector class template constructors inherited constructors (using vector<T>::vector;):

    template< class T> struct Vector : public std::vector<T> {
        typedef typename std::vector<T>::size_type size_type;
    
        using std::vector<T>::vector;
    
        T& operator[](unsigned int i) // rather than return at(i);
        {
            if (i<0||this->size()<=i) throw Range_error(i);
            return std::vector<T>::operator[](i);
        }
        const T& operator[](unsigned int i) const
        {
            if (i<0||this->size()<=i) throw Range_error(i);
            return std::vector<T>::operator[](i);
        }
    };
    
Comments