Пересылка cv-ref-qualifier для функций-членов

Если нет других перегрузок (скажем, f(T &) или же f(volatile T &&)) (функции) шаблона функции template< typename T > f(T &&);, затем T && это так называемый экспедиционная ссылка, а также T либо U, или же U & для некоторых резюме квалифицированных тип U, Но для резюме-реф-классификаторы функций-членов такого правила нет. В struct S { void f() && { ; } }; S::f() всегда имеет квалификатор rvalue-reference.

В общем коде было бы очень полезно избегать определения 4 (или даже 8, если мы также рассмотрим volatile квалификатор) перегрузки некоторой функции-члена, если все они выполняют одно и то же.

Другая проблема, которая возникает таким образом, это невозможность определить эффективную резюме-реф-классификатор из *this в определенном смысле. Следующий код не позволяет определить, является ли реф-классификатор функции-члена operator () является && из &,

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

Но было бы очень хорошо, если бы был синтаксис выше. То есть decltype((*this)) обозначать точно резюме-реф-квалифицирован тип *this, Не было бы серьезным изменением ввести такой синтаксис в будущую версию C ++ стандарт на мой взгляд. Но && как переадресация cv-ref-qualifier есть (и похоже на упущение комитета (а именно, основной языковой рабочей группы)).

В другой последовательности можно обозначить как функцию-член резюме-реф-классификатор а также резюме-реф-квалифицирован тип *this в его тело: auto &&, decltype(&&) и т.п.

Есть ли предложение по этому вопросу, подготовленное для использования в C ++ 17?

11

Решение

Да, есть такие предложения.

Фон:

Поскольку у нас уже есть пересылка ссылок в шаблонных функциях, вы можете просто превратить вашу функцию-член в функцию-шаблон (и защитить ее с помощью enable_if от использования с любым другим классом, чем F, если необходимо).

Теперь, может быть, вы хотите, чтобы вы действительно, действительно хотели использовать вашу функцию в качестве функции-члена, потому что вам действительно очень нравится этот синтаксис намного лучше.

Предложения:

Посмотрите предложения по унифицированному синтаксису вызовов, например: n4174

Если что-то подобное будет принято, то вы сможете использовать свободные функции, такие как функции-члены первого аргумента. Это будет охватывать пример кода, который вы указали в первом комментарии. Следует признать, что это не распространяется на operator (), но я считаю, что незначительная неприятность по сравнению с записью 8 перегрузок 🙂

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]