jeudi 26 janvier 2017

Why is it illegal : copying vector of pointers into a vector of pointers to constants

The issue

The following code does not compile in C++11 (nor C++14). I understand the error output from the compiler, but why isn't it allowed by the standard?

//main.cpp

#include <vector>

int main(void)
{
    double a = 3.0;
    double b = 3.0;

    //It works with mere pointers
    const double* ptrToConst = &a;
    /***/ double* ptrToObj   = &a;
//  ptrToObj = ptrToConst; //Illegal : that's understandable…
    ptrToConst = ptrToObj;   //Works

    //But the same doesn't work with vectors to pointers
    std::vector<const double*> ptrsToConst = {&a, &b};
    std::vector</***/ double*> ptrsToObj   = {&a, &b};
//  ptrsToObj = ptrsToConst; //Illegal : that's understandable
    ptrsToConst = ptrsToObj; //Illegal : but why?!
}

The error comes from the line ptrsToConst = ptrsToObj. Indeed, it does not seem possible to copy a vector of pointers std::vector<T*> into a vector of pointers to constants std::vector<const T*>. Note that in both cases, the pointers themselves are not constant.

Why would this operation be illegal? What would be the most elegant work around?


Further details

If I compile by invoking clang++ --std=c++11 main.cpp, the following error message displays:

main.cpp:19:17: error: no viable overloaded '='
    ptrsToConst = ptrsToObj; //Illegal : but why?!
    ~~~~~~~~~~~ ^ ~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_vector.h:436:7: note: candidate
      function not viable: no known conversion from 'vector<double *, allocator<double *>>' to 'const
      vector<const double *, allocator<const double *>>' for 1st argument
      operator=(const vector& __x);
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_vector.h:448:7: note: candidate
      function not viable: no known conversion from 'vector<double *, allocator<double *>>' to 'vector<const
      double *, allocator<const double *>>' for 1st argument
      operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_vector.h:470:7: note: candidate
      function not viable: no known conversion from 'std::vector<double *>' to 'initializer_list<value_type>' (aka
      'initializer_list<const double *>') for 1st argument
      operator=(initializer_list<value_type> __l)
      ^
1 error generated.

Trying the same with gcc (g++) spawns similar error messages.

Apparently, the way vectors are implemented does not allow for the operation I am trying to perform. However that is a safe operation regarding const correctness, right?

Aucun commentaire:

Enregistrer un commentaire