11

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

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

以这种方式出现的另一个问题是,在特定意义上定义有效的cv-ref-qualifier是不可能的。*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))表示精确的cv-ref-qualified类型*this。在我看来,将这样的语法引入到即将到来的C++标准版本中并不是一个重大改变。但是&&作为转发 cv-ref-qualifier是(而且它看起来像是委员会的遗漏(即核心语言工作组))。

另一个序列可以在其主体中表示成员函数cv-ref-qualifiercv-ref-qualified类型:等。*thisauto &&decltype(&&)

是否有关于此问题的提案,准备在C++17中使用?

4

1 回答 1

1

是的,有这样的提议。

背景:

由于我们已经在模板函数中有转发引用,因此您可以简单地将您的成员函数转换为模板友元函数(如果需要,可以通过enable_if与 . 以外的任何其他类一起使用来保护它F)。

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

提案:

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

如果接受类似的东西,您将能够使用自由函数,如第一个参数的成员函数。这将涵盖您在第一条评论中链接的示例代码。诚然,它不会涵盖 operator(),但我认为与编写 8 个重载相比,这是一个小麻烦 :-)

于 2016-01-31T10:04:50.103 回答