0

I am trying to run an example with vector of reference wrappers, but run into compilation error at the vector variable declaration. Here is the code:

#include <iostream>
#include <vector>
#include <functional>

using namespace std;

struct Base
{
    virtual void print() = 0;
};

struct X1: public Base
{
    void print() override
    {
        cout << "X1\n";
    }
};

struct X2: public Base
{
    void print() override
    {
        cout << "X2\n";
    }
};


int main()
{
    X1 x1;
    X2 x2;
    vector<reference_wrapper<Base>> X{cref(x1), cref(x2)};
}

The vector constructor with std::initializer_list exists. The type of the passed values must be const T, which std::cref returns, so why does it complain:

/home/u1/sandbox/c++/trash/untitled/main.cpp:33: error: no matching function for call to ‘std::vector<std::reference_wrapper<Base> >::vector(<brace-enclosed initializer list>)’
     vector<reference_wrapper<Base>> X{cref(x1), cref(x2)};
                                                         ^

? (building with gcc -std=c++17 if it matters)

Student4K
  • 916
  • 2
  • 9
  • 20

1 Answers1

5

You're initializing a non-const Base with const wrappers:

vector<reference_wrapper<Base>> X{cref(x1), cref(x2)};

use const Base instead:

vector<reference_wrapper<const Base>> X{cref(x1), cref(x2)};
Paul Evans
  • 27,315
  • 3
  • 37
  • 54
  • Tried ``const Base`` for template argument as well as ``Base`` with ``std::ref`` (instead of ``std::cref``) to no avail. – Student4K Sep 02 '19 at 14:31
  • 2
    @Student4K Either use `const Base` with `std::cref` or `Base` with `std::ref`. Both work for me: https://wandbox.org/permlink/DxpPdk3q1WDSB6uy. Note that `const Base` works even with `std::ref`. – Daniel Langr Sep 02 '19 at 14:45
  • 1
    Hm... looks like only gcc 9.x compiles the code, whereas 7.x and 8.x do not. – Student4K Sep 02 '19 at 15:00