转发成员函数的cv-ref-qualifier

Forwarding cv-ref-qualifier for member functions

本文关键字:cv-ref-qualifier 函数 成员 转发      更新时间:2023-10-16

如果(成员)函数模板template< typename T > f(T &&);没有其他重载(如f(T &)f(volatile T &&)),则T &&为所谓的转发引用TUU &,对于某些cv合格的类型U。但是对于成员函数的cv-ref-qualifiers没有这样的规则。在struct S { void f() && { ; } };中,S::f()总是有右值-引用限定符。

在泛型代码中,避免某些成员函数的4(甚至8,如果我们还考虑volatile限定符)重载的定义是非常有用的,在所有成员函数都做一般相同的事情的情况下。

以这种方式产生的另一个问题是,不可能在特定意义上定义*this的有效cv-ref-限定符。下面的代码不允许确定成员函数operator ()ref-限定符是否为&&&
#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的确切cv-ref-qualified类型。在我看来,在 c++ 标准的下一个版本中引入这样的语法并不是一个突破性的变化。但是&&作为转发cv-ref-qualifier是(并且它看起来像是委员会(即核心语言工作组)的遗漏)。

另一个序列可以同时表示*this的成员函数cv-ref-qualifiercv-ref-qualified类型:auto &&decltype(&&)等。

是否有关于这个问题的建议,准备在 c++ 17使用?

是的,有这样的建议。

背景:

因为我们已经在模板函数中有了转发引用,你可以简单地把你的成员函数变成模板友元函数(如果需要的话,可以通过enable_if保护它不被F以外的任何其他类使用)。

现在,也许你非常非常想将你的函数用作成员函数,因为你非常非常喜欢这种语法。

建议:

查找统一调用语法建议,例如:n4174

如果接受这样的内容,则可以使用自由函数,例如第一个实参的成员函数。这将涵盖您在第一个注释中链接的示例代码。不可否认,它不会涵盖operator(),但我认为与编写8个重载相比,这是一个小麻烦:-)