Question

I'm trying to get read-only access to object's field using pointer-to-member, however I get "Access violation reading location ..." error.

template<typename X, typename Y>
class a
{
public:
    a(Y X::*field): f([&](const X &x) { return x.*field; }) {} // error
    a(Y (X::*method)() const): f([=](const X &x) { return (x.*method)(); }) {}
    a(std::function<Y(const X &)> f): f(f) {}

    Y operator()(const X &x) const { return f(x); }

private:
    std::function<Y(const X &)> f;
};

class X
{
public:
    X(): x(1) {}
    int x;
    int f() const { return x + 1; }
};

int main()
{
    X x;
    a<X const, int> a1(&X::x);
    a<X, int> a2(&X::f);
    a<X, int> a3([](const X &x) { return x.f() + x.x; });
    std::cout << a1(x) << a2(x) << a3(x) << std::endl;
    return 0;
}

I tried to add const qualifier to field definition, but that didn't help.

Was it helpful?

Solution

The problem is in the way you capture things in your lambda.

a(Y X::*field): f([&](const X &x) { return x.*field; }) {}

You use a reference to field, which is valid only in the constructor. When the constructor ends, you have a dangling reference.

A way to fix would be to copy parameters :

a(Y X::*field): f([=](const X &x) { return x.*field; }) {}

The creation of a3 fails because you do not have appropriate constructor.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top