std::optional<T> assignment operators

61 views Asked by At

My reference is to options (4), (5) and (6) of std::optional::operator=

Given the premise that

The class template std::optional manages an optional contained value, i.e. a value that may or may not be present.

(4) from the link states in the description:

The function does not participate in overload resolution unless std::decay_t<U> (until C++20)std::remove_cvref_t<U> (since C++20) is not std::optional<T>, std::is_constructible_v<T, U> is true, std::is_assignable_v<T&, U> is true, and at least one of the following is true:

    T is not a scalar type;
    std::decay_t<U> is not T.

The implication above seems to be that U is not std::optional<T>, but since std::optional<T> could be T, how does this condition correlate to the other condition

std::is_constructible_v<T, U> is true, std::is_assignable_v<T&, U> is true

Also if T is not a scalar type, how can the assignment possibly work if std::decay_t<U> is not T?

(5) and (6) state

These overloads do not participate in overload resolution unless the following conditions are met:

    T is not constructible, convertible, or assignable from any expression of type (possibly const) std::optional<U>, i.e., the following 12 type traits are all false:
        std::is_constructible_v<T, std::optional<U>&>
        std::is_constructible_v<T, const std::optional<U>&>
        std::is_constructible_v<T, std::optional<U>&&>
        std::is_constructible_v<T, const std::optional<U>&&>
        std::is_convertible_v<std::optional<U>&, T>
        std::is_convertible_v<const std::optional<U>&, T>
        std::is_convertible_v<std::optional<U>&&, T>
        std::is_convertible_v<const std::optional<U>&&, T>
        std::is_assignable_v<T&, std::optional<U>&>
        std::is_assignable_v<T&, const std::optional<U>&>
        std::is_assignable_v<T&, std::optional<U>&&>
        std::is_assignable_v<T&, const std::optional<U>&&>. 

Again, std::optional<U> could be U, and if so how does the assignment work?

The description further reads:

For overload (5), std::is_constructible_v<T, const U&> and std::is_assignable_v<T&, const U&> are both true.
For overload (6), std::is_constructible_v<T, U> and std::is_assignable_v<T&, U> are both true

Wouldn't this be the case if std::optional<U> were to contain U?

Should std::optional<T> and std::optional<U> be assumed have no valid values to resolve the above apparent contradictions?

Based on the test code below, std::optional<T> and T are distinct types.

#include<optional>
#include<type_traits>
#include<string>
#include<ios>
#include<iostream>

using std::optional;
using std::is_same;
using std::string;
using std::boolalpha;
using std::cout;
using std::endl;

int main (){
  optional<string> opt("yes");
  string s("yeah"); 

  cout << boolalpha << is_same<decltype(opt),decltype(s)>::value << endl;

  return 0;
}
0

There are 0 answers