xtensor-stack / xtensor

C++ tensors with broadcasting and lazy computing
BSD 3-Clause "New" or "Revised" License
3.33k stars 398 forks source link

Accessing elements of a view on a const array #721

Closed PerretB closed 6 years ago

PerretB commented 6 years ago

Hi,

there seems to be a problem that prevents accessing to the elements of a view on a const array with the operator(). Exemple :

void foo(){
        const xt::xarray<int> a1{{0, 1}, {2, 3}};
        auto a2 = xt::view(a1, 1, xt::range(1,2));
        auto a3 = xt::flatten(a1);

        int v1 = a1(0,0);
        int v2 = a2(0); // error: binding ‘const int’ to reference of type ‘... {aka int&}’ discards qualifiers
        int v3 = a3(0); // error: binding ‘const int’ to reference of type ‘... {aka int&}’ discards qualifiers
    }

My configuration is:

xtl : 0.4.3
xtensor : 0.15.6
xsimd : 0.4.1.1
gcc 5.4.0

Thanks for all the amazing work !

wolfv commented 6 years ago

Does it work if you make your view const as well (e.g.

const auto a2 = xt::view(a1, 1, xt::range(1,2));
PerretB commented 6 years ago

yes !

I'm quite a c++ newbie, but shouldn't have the compiler deduced the const in this case ?

wolfv commented 6 years ago

Yes, it's something that we can probably add. We can discuss this tomorrow.

JohanMabille commented 6 years ago

I'm quite a c++ newbie, but shouldn't have the compiler deduced the const in this case ?

xview provides two overloads of operator(), one that is const and returns a const reference, and another non const that returns a non const reference.

When you write a2(0), the compiler considers the declaration of a2 to decide wich overload of operator() to call. In Your case, since a2 is not declared as const, the non const version is called (and that's the standard behavior).

The problem here is that the non const overload of operator() should return a const reference when the underlying expression is const.

PerretB commented 6 years ago

Thank you for the explanation and the very fast answer