c++c++11ranged-loops

error: binding ‘const double’ to reference of type ‘double&’ discards qualifiers


I receive error

binding ‘const double’ to reference of type ‘double&’ discards qualifiers

when compiling:

g++ -std=c++11 main.cpp
main.cpp: In function ‘Point square(const Point&)’:
main.cpp:14:28: error: binding ‘const double’ to reference of type ‘double&’ discards qualifiers
  for(double &a:{Q.x,Q.y,Q.z})
                            ^

While there are other questions online about this error, I am looking for a solution this particular code. I insist on using ranged for.

#include <iostream>
#include <vector>

class Point
{
public:
    double x,y,z;
};

Point square(const Point &P)
{
    Point Q=P;
    for(double &a:{Q.x,Q.y,Q.z})
        a*=a;
    return Q;
}

int main()
{
    Point P{0.1,1.0,10.0};
    Point Q=square(P);
    std::cout<<"----------------"<<std::endl;
    std::cout<<"Q.x: "<<Q.x<<std::endl;
    std::cout<<"Q.y: "<<Q.y<<std::endl;
    std::cout<<"Q.z: "<<Q.z<<std::endl;
    std::cout<<"----------------"<<std::endl;
    return 0;
}

Solution

  • An initializer list created by {Q.x,Q.y,Q.z} in context of your for is still based on a separate array of values. Even if you somehow managed to modify these values, it still wouldn't affect your Q, which is apparently your intent. But you can't modify them anyway, since that array consists of const elements (which is what the compiler is telling you).

    If you want a ranged for you can use an old C-era trick

    for (double *a : { &Q.x, &Q.y, &Q.z })
      *a *= *a;
    

    or, alternatively

    for (auto a : { std::ref(Q.x), std::ref(Q.y), std::ref(Q.z) })
      a *= a;