Why std::is_assignable doesn't work with primitive types? (Confirmation)
Asked Answered
Q

2

6

To be more specific why std::is_assignable_v<int, int> << '\n'; returns false? Is it because an int has no overloaded assignment operator (being a primitive type and all)?

(by the way std::is_trivially_assignable_v<int, int> gives false too.)

Note that this: struct Structure {}; std::is_assignable<class Structure, class Structure>::value; would return true, because an overloaded assignment operator is implicitly defined for Structure.

Am i correct so far? If so then I suppose it wouldn't be trivial to enhance is_assignable to accept primitive types as well? Otherwise, any hints for such a possible work-around?

Quigley answered 20/9, 2018 at 16:23 Comment(2)
You could check if the type is_fundemental or is_assignablePerishable
Your example is discussed right on en.cppreference.com/w/cpp/types/is_assignableDecanal
T
6

If the expression std::declval<T>() = std::declval<U>() is well-formed in unevaluated context

std::is_assignable<int, int>::value << '\n' // 1 = 1; wouldn't compile

https://en.cppreference.com/w/cpp/types/is_assignable

Truelove answered 20/9, 2018 at 16:28 Comment(0)
C
11

An int cannot be assigned to an int. If you pass int& as a first argument instead, then, as expected, both is_assignable and is_trivially_assignable return true.

cppreference, godbolted

#include <type_traits>

int main()
{
    static_assert(!std::is_assignable_v<int, int>);
    static_assert(std::is_assignable_v<int&, int>);
    static_assert(!std::is_trivially_assignable_v<int, int>);
    static_assert(std::is_trivially_assignable_v<int&, int>);

    return 0;
}

A not so intuitive part — is_assignable_v<mytype, mytype> is true is because mytype{} = mytype{}; works too, and only is_assignable_v<mytype const, mytype> is false.

Contemn answered 20/9, 2018 at 16:27 Comment(4)
I could not understand why int is not assignable by int, can you explain more?Messene
@Jeka, I guess because you cannot say int{42} = int{24} (error: temporary as an lvalue), but you can say mytype{42} = mytype{24} (good question, why?). All is_assignable does is checking if assignment expression is well-formed.Contemn
@Messene He meant in the context of std::declval (used by std::is_assignable internally) which returns an rvalue reference of its argument (compile time unevaluated context only). And as bobah explained you can't assign to an rvalue. Once I saw his wording there I knew it would be confusing to people.Quigley
@Nik-Lz - thanks for spelling it out, my comment was not less confusing than the std wording, I realized.Contemn
T
6

If the expression std::declval<T>() = std::declval<U>() is well-formed in unevaluated context

std::is_assignable<int, int>::value << '\n' // 1 = 1; wouldn't compile

https://en.cppreference.com/w/cpp/types/is_assignable

Truelove answered 20/9, 2018 at 16:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.