copy assignment operator with volatile qualifier

160 Views Asked by At

Below, I used template<int = 0> learnt from @Daniel McLaury in here.

#include <type_traits>

template<typename T>
struct A_base {
    int val;

    // template<int = 0> // needs it to make MSVC work
    volatile T& operator=(const volatile T& a) volatile {
        val = a.val;
        return static_cast<volatile T&>(*this);
    }

    T& operator=(const volatile T& a) {
        val = a.val;
        return static_cast<T&>(*this);
    }
};

struct A : A_base<A> {
    using A_base::operator=;

    A() = default;
    A(const A&) = default;

    template<int = 0>
    A(const volatile A& a) {
        *this = a;
    }
};

void test(volatile A* p) {
    static_assert(std::is_trivial_v<A>);

    A a = *p;
    *p = a;
}

Both GCC and Clang can compile the code, but MSVC failed:

error C2678: binary '=': no operator found which takes a left-hand operand of type 'volatile A' (or there is no acceptable conversion) message : could be 'A &A::operator =(const A &)' message : or
'A_base &A_base::operator =(const A_base &)' message : or
'A_base &A_base::operator =(A_base &&)' message : while trying to match the argument list '(volatile A, A)'

I need template<int = 0> on the CRTP volatile T& operator=(const volatile T& a) volatile; to make MSVC work.

I guess it's because templated code has lower priority in the overload resolution rule, is that true?

Could someone review my code, and explain which part is illegal/undefined by C++ standard?

Thank you very much.

0

There are 0 best solutions below