Thank you and Michael Hava for the updates, it turns out my C++ knowledge needs to be updated to C++17.

Here are some of my thoughts about your concern,

1. the "&&?" notation
we may treat "&&" as a token having two "&", and each "?" can optionally remove one "&",
following the rule, "&&??" can be used to optionally remove two "&" from "&&" with "??".

a) const?    -> (), const   //2 variations with single "?"
b) &?        -> (), &       //2 variations with single "?"
c) &&?       -> &, &&       //2 variations with single "?"
d) &&??      -> (), &, &&   //3 variations with double "?" ("??")

here, left side is the notations, right side are the variations of the final tokens to replace the notation, "()" means no token (notation removed)
by explaining "?" like this, developer may able to accept this concept easily. though "&?", and "&&??" are hardly needed, but they may still be usefully, for example

//declared with "&?"
int&? max(int&? a, int&? b) { return a > b ? a : b; }  //"&?" can appear more than once in a declaration

//result of "&?"
int max(int a, int b) { return a > b ? a : b; }        //all "&?" are removed
int& max(int& a, int& b) { return a > b ? a : b; }     //all "&?" are replaced with "&"

2. the rule
the rule which I would like to suggest for notation "const?", "&?", "&&?", "&&??" appeared in a declaration/definition of a function/method.
a) each notation may appear multiple times in a declaration.
b) each notation may appear multiple times in a definition (including its body).
b) for each declaration or definition, usually only one reference type notation ( "&?", "&&?", "&&??") can appear, otherwise, too many combinations (if really needed, this restriction can be ignored)
c) for each declaration or definition, when a notation is found, a set of declaration/definition will be generated according to the variations of notation
d) for each generated declaration or definition, all appearances of same notation are replaced with same token.
e) if the generated declaration/definition still contains other notation, repeat c)

3. the return value
I think the compiler should be updated to treat a reference to member value of rvalue object as rvalue reference as well, for example

class A
{
  int value;
  int&  value() &  { return value; } //okay
  int&& Value() && { return value; } //should be okay, no std::move() should be needed, as this method applies to A&& (rvalue object)
  int&& Value() &  { return value; } //wrong, as this method applies to A& (lvalue object), std::move() should be required here
}

if compiler can to work as expected, we can write method like with new notation

const? int&&? Value() const? &&? { return value; }

Best Regards,

Jianping

On 12/17/2019 06:07 AM, Barry Revzin wrote:
On Sun, Dec 15, 2019 at 11:51 PM jianping z <zjpwork@gmail.com> wrote:
If we need both "const?" and "&&?" in a declaration/definition of a class method or a normal function, I think it's not difficult for compiler to handle them.

The question isn't so much if it's difficult for the compiler to handle. The difficulty for the compiler probably lies in the fact that the ? can appear arbitrarily late in a declaration. The question is more: what are the specific rules you're proposing and how do they work?

On Mon, Dec 16, 2019 at 12:58 AM jianping z <zjpwork@gmail.com> wrote:
do we really need to write "return std::move(value)" instead of simply "return value"? the new compiler should be able to handle it automatically for method with return type T&&.

Yes. The language will only implicitly move from things that are imminently being destroyed: either local variables or function parameters that have automatic storage duration, or (in C++20) also a few cases where the variable being returned has rvalue reference type. None of these apply here - if you want to move from a member variable, you have to do so explicitly.

On Mon, Dec 16, 2019 at 3:06 PM jianping z <zjpwork@gmail.com> wrote:

also, for your example, do we really need following 2 member methods returning value of  type "T&&" and "const T&&"?

    auto operator*() &&      -> T&&       { return std::move(value); }
    auto operator*() const&& -> T const&& { return std::move(value); }

do you have code example to show the possible usage of these 2 methods?

The first one is clear - if we have an rvalue optional we want to be able to move from its internals instead of copying. The second one, less so. const rvalues are a bit strange, and you can't really move from a const rvalue anyway so there isn't performance gain there if we omit that overload -- but the goal here is to preserve the value category of the input. We get an rvalue in --> we get an rvalue out. The preservation ensures, for instance, that this fails:

auto foo() -> optional<int> const;
std::ref(foo().value()); // foo() is a const rvalue, foo().value() is a int const&&
                         // and this overload is deleted for rvalues

If we didn't provide the const rvalue overload, foo().value() would have type int const& and we could pass it to std::ref.

Barry