0

I expected the following program to print "11" but it actually prints "01" so it seems like the first assignment fails.

struct A
{
    A(int i = 0) : i_(i) {}
    int i_;
};

int main()
{
    A x(1);
    A y;
    static_cast<A>(y) = x; // *** Fails to assign ***
    std::printf("%i", y.i_);
    y = x;
    std::printf("%i", y.i_);
}

If I use a primitive type likeint instead of A then int x = 1; int y; static_cast<int>(y) = x; does assign the value 1 to x. Is there some way I can get it to work for custom types? I tried adding operator A() { return *this; } to struct A but that didn't work.

Obviously this is a stupid program but the problem arises in a template function where I have static_cast<std::remove_const<T>::type>(y) = x and it was working fine for primitive types but just now failed for a custom type.

George Skelton
  • 1,095
  • 1
  • 10
  • 22

1 Answers1

4

As with any cast, static_cast<A>(y) is a temporary copy of y. You can cast to a reference type instead (static_cast<A&>(y)); more generally, you could achieve this with std::add_lvalue_reference.

For the more specific example you described, you'll need const_cast rather than static_cast, but the basic principle is the same.

Here's an example that compiles, but has UB because of the modification of a const object (and thus returns 0, not 42). Without knowing more about what you're trying to do, I shan't attempt to disguise that for the purposes of this example:

#include <iostream>
#include <type_traits>

template <typename T>
T foo(T val)
{
    T x{};

    using not_const = typename std::remove_const<T>::type;
    using ref_type  = typename std::add_lvalue_reference<not_const>::type;

    const_cast<ref_type>(x) = val;

    return x;
}

int main()
{
    std::cout << foo<const int>(42) << '\n';
}
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055