Search code examples
c++castingreferencec++17any

std::any object cast to reference type, change its value, but original object is not changed


I was trying to see if std::any object can cast to reference type, and see whether changing the casted reference means to change original object. As below:

struct My {
    int m_i;
    My() : m_i(1) {}
    My(const My& _) : m_i(2) {}
    My(My&& m) : m_i(3) {};
    My& operator = (const My& _) { m_i = 4; return *this; }
    My& operator = (My&& _) { m_i = 5; return *this; }
};

int main() {
    any a = My();
    My& b2 = any_cast<My&>(a);
    b2.m_i = 6;
    cout << any_cast<My>(a).m_i << endl;
    return 0;
}

It prints 2. For my I expected that, as long as b2 is a reference, I hope changing b2.m_i will effect a.m_i, right? But result seems not as my expectation.

Where did I get wrong, is my expectation valid?

Thanks!


Solution

  • Look at your example without any any:

    #include <any>
    #include <iostream>
    using std::cout;
    using std::endl;
    using std::any;
    using std::any_cast;
    
    struct My {
        int m_i;
        My() : m_i(1) {}
        My(const My& _) : m_i(2) {}
        My(My&& m) : m_i(3) {};
        My& operator = (const My& _) { m_i = 4; return *this; }
        My& operator = (My&& _) { m_i = 5; return *this; }
    };
    
    int main() {
        My a = My();
        My& b2 = a;
        b2.m_i = 6;
        cout << static_cast<My>(a).m_i << endl;
    }
    

    Output is:

    2
    

    Because static_cast<My>(a) is creating a temporary copy of a and your copy assigns 2 to the member. You can use static_cast<My&>(a) to not make a copy.

    After removing your somewhat weird copy and assignment, you can also get the same result with any:

    struct My {
        int m_i = 1;
    };
    
    int main() {
        any a = My();
        My& b2 = any_cast<My&>(a);
        b2.m_i = 6;
        cout << any_cast<My>(a).m_i << endl;  // copy
        cout << any_cast<My&>(a).m_i << endl; // no copy
    }
    

    Output:

    6
    6