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;
}