1

取以下成员函数:

struct T {
    template <typename X> void f(X&& x) { /* ... */ }
};

在这种情况下,x是一个转发引用,因为&&它用于模板内的函数参数。这正如预期的那样。

现在使用这个函数:

struct T {
    template <typename X> void f(X&& x) && { /* ... */ }
};

我希望this会以类似的方式对待它;作为转发参考。因此,我希望以下程序能够正常编译和运行:

#include <iostream>

struct T {
    template <typename X>
    bool operator<(X&& rhs) && {
        std::cout << "&&" << std::endl;
        return true;
    }
};

int main() {
    T t;
    std::cout << (t < T()) << std::endl;
    return 0;
}

但是使用 GCC 4.8.4 和 6.0.1,它不会。相反,我得到以下信息:

rvalue.cpp: In function ‘int main()’:
rvalue.cpp:13:25: error: passing ‘T’ as ‘this’ argument of ‘bool T::operator<(X&&) && [with X = T]’ discards qualifiers [-fpermissive]
 std::cout << (t < T()) << std::endl;

似乎this没有进行转发参考。这是正确的还是错误的?是否应该this被视为转发参考?标准的哪一部分规定了这一点?

4

3 回答 3

3

这里的两个&&s` 被区别对待:

struct T {
    template <typename X> void f(X&& x) && { /* ... */ }
};

您是正确的,因为这x是一个转发参考。但是&&右边是对对象实例的限定。在这种情况下,f()只有在对象实例是右值时才能调用(也许更令人困惑的是,第一个&&作为x转发引用,而第二个&&将隐式对象参数作为右值引用)。那是:

T().f(4); // ok

T t;
t.f(4); // error

这与资格认证的工作方式相同const

struct X { void f(); };
const X cx;
cx.f(); // error
于 2016-08-30T15:58:53.787 回答
2

函数末尾的引用限定符声明operator<只应在 LHS 是临时的时调用。请记住,运算符可以像任何其他成员函数一样被调用,所以你所拥有的是

t.operator<(T())

并且t不是暂时的。

如果我们将您的示例更改为

std::cout << (T() < t) << std::endl;

然后它工作得很好,因为你调用的对象operator<是一个临时对象。

于 2016-08-30T15:58:23.717 回答
0

该成员只能在右值operator<() &&上调用,因此如下:

t < T()

不会工作,因为t不是rvalue - 它是lvalue

以下应该有效:

std::move(t) < T()

这也是:

T{} < T{}

请注意,我已经使用{}过它们,因为我对它们更满意,它们的工作并不令人惊讶。

于 2016-08-30T15:58:54.310 回答