mercredi 30 septembre 2015

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 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)) is 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)).

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

Aucun commentaire:

Enregistrer un commentaire