Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forwarding cv-ref-qualifier for member functions

If there are no another overloadings (say, f(T &) or f(volatile T &&)) of a (member) function template template< typename T > f(T &&);, then T && is so-called forwarding reference, and T is either U, or U & for some cv-qualified type U. But for cv-ref-qualifiers of member functions there is no such a rule. In struct S { void f() && { ; } }; a S::f() has always rvalue-reference qualifier.

In generic code it would be very useful to avoid a definition of 4 (or even 8, if we also consider volatile qualifier) overloadings of some member function, in cases if all of them doing generally the same thing.

Another problem that arises in this way, it is impossibility to define an effective cv-ref-qualifier of *this in a particular sense. Following code not allows one to determine whether the ref-qualifier of a member function operator () is && of &.

#include <type_traits>
#include <utility>
#include <iostream>

#include <cstdlib>

#define P \
{                                                                       \
    using this_ref = decltype((*this));                                 \
    using this_type = std::remove_reference_t< this_ref >;              \
    std::cout << qual() << ' '                                          \
              << (std::is_volatile< this_type >{} ? "volatile " : "")   \
              << (std::is_const< this_type >{} ? "const " : "")         \
              << (std::is_lvalue_reference< this_ref >{} ? "&" : "&&")  \
              << std::endl;                                             \
}

struct F
{
    constexpr int qual() & { return 0; }
    constexpr int qual() const & { return 1; }
    constexpr int qual() && { return 2; }
    constexpr int qual() const && { return 3; }
    constexpr int qual() volatile & { return 4; }
    constexpr int qual() volatile const & { return 5; }
    constexpr int qual() volatile && { return 6; }
    constexpr int qual() volatile const && { return 7; }
    void operator () () & P
    void operator () () const & P
    void operator () () && P
    void operator () () const && P
    void operator () () volatile & P
    void operator () () volatile const & P
    void operator () () volatile && P
    void operator () () volatile const && P
};

int
main()
{
    {
        F v;
        F const c{};
        v();
        c();
        std::move(v)();
        std::move(c)();
    }
    {
        volatile F v;
        volatile F const c{};
        v();
        c();
        std::move(v)();
        std::move(c)();
    }
    return EXIT_SUCCESS;
}

But it would be very nice, if there was above syntax. I.e. decltype((*this)) denote exact cv-ref-qualified type of *this. It would not be a breaking-change to introduce such a syntax into coming version of the C++ standard at my mind. But && as forwarding cv-ref-qualifier is (and it looks like an omission of the committee (namely, core language working group)).

Another sequence is possible to denote both the member function cv-ref-qualifier and cv-ref-qualified type of *this into its body: auto &&, decltype(&&) etc.

Is there a proposal regarding this issue, prepared for use in C++17?

like image 388
Tomilov Anatoliy Avatar asked Sep 30 '15 06:09

Tomilov Anatoliy


1 Answers

Yes, there are such proposals.

Background:

Since we already have forwarding references in template functions, you could simply turn your member function into a template friend function (and protect it via enable_if from being used with any other class than F, if required).

Now, maybe you want your really, really want to use your function as a member function, because you really, really like that syntax so much better.

The proposals:

Look up unified call syntax proposals, for instance: n4174

If something like that is accepted, it you will be able to use free functions like member functions of the first argument. This would cover the example code you linked in your first comment. Admittedly, it would not cover operator(), but I consider that a minor nuisance compared to writing 8 overloads :-)

like image 56
Rumburak Avatar answered Oct 21 '22 03:10

Rumburak