gpt4 book ai didi

c++ - 使用 ref-qualifiers 的重载决议

转载 作者:太空宇宙 更新时间:2023-11-04 13:47:39 36 4
gpt4 key购买 nike

在使用 ref-qualified 函数重载时,我从 GCC (4.8.1)Clang(2.9 和主干) 得到了不同的结果。考虑以下代码:

#include <iostream>
#include <utility>

struct foo
{
int& bar() &
{
std::cout << "non-const lvalue" << std::endl;
return _bar;
}
//~ int&& bar() &&
//~ {
//~ std::cout << "non-const rvalue" << std::endl;
//~ return std::move(_bar);
//~ }
int const& bar() const &
{
std::cout << "const lvalue" << std::endl;
return _bar;
}
int const&& bar() const &&
{
std::cout << "const rvalue" << std::endl;
return std::move(_bar);
}

int _bar;
};

int main(int argc, char** argv)
{
foo().bar();
}

Clang 编译它并输出 "const rvalue",而 GCC 认为这是一个含糊不清的调用,两个 const 限定函数都成为最可行的候选人。如果我提供所有 4 个重载,那么两个编译器都会输出 "non-const rvalue"

我想知道哪个编译器 - 如果有的话 - 正在做正确的事情,以及相关的标准部分是什么。

注意: 这一点真正重要的原因是实际代码将两个 const 限定函数都声明为 constexpr。当然,没有输出到 std::cout 并且使用 static_cast 代替 std::move,因此它们是有效的 constexpr 定义。并且由于在 C++11 constexpr 中仍然暗示 const,因此无法提供示例代码中注释掉的重载,因为它会重新定义 const -限定右值重载。

最佳答案

首先,隐式对象参数按照 13.3.1.4 被视为普通参数:

For non-static member functions, the type of the implicit object parameter is

— “lvalue reference to cv X” for functions declared without a ref-qualifier or with the & ref-qualifier

— “rvalue reference to cv X” for functions declared with the && ref-qualifier

where X is the class of which the function is a member and cv is the cv-qualification on the memberfunction declaration.

所以你的要求等同于以下内容:

void bar(foo&);
void bar(foo&&);
void bar(const foo&);
void bar(const foo&&);

int main()
{
bar(foo());
}

表达式 foo() 是一个纯右值类。

其次,非常量左值引用版本不可行,因为纯右值无法绑定(bind)到它。

这给我们留下了三个可行的重载解析函数。

每个都有一个隐式对象参数(const foo&foo&&const foo&&),所以我们必须对这三个进行排序以确定最佳匹配。

在所有这三种情况下,它都是一个直接绑定(bind) 引用绑定(bind)。这在 declarators/initialization (8.5.3) 中有描述。

三种可能的绑定(bind)(const foo&foo&&const foo&&)的排名在 13.3.3.2.3 中有描述:

Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if

  • S1 and S2 are reference bindings and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier [this exception doesn't apply here, they all have ref-qualifiers], and S1 binds an rvalue reference to an rvalue [a class prvalue is an rvalue] and S2 binds an lvalue reference.

这意味着 foo&&const foo&& 都比 const foo& 好。

  • S1 and S2 are reference bindings, and the types to which the references refer are the same type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 refers.

这意味着 foo&& 优于 const foo&&

所以 Clang 是对的,它是 GCC 中的一个错误。 foo().bar() 的重载排名如下:

struct foo
{
int&& bar() &&; // VIABLE - BEST (1)
int const&& bar() const &&; // VIABLE - (2)
int const& bar() const &; // VIABLE - WORST (3)
int& bar() &; // NOT VIABLE

int _bar;
};

GCC 中的错误似乎纯粹适用于隐式对象参数(使用 ref-qualifiers),对于普通参数,它似乎获得正确的排名,至少在 4.7.2 中是这样。

关于c++ - 使用 ref-qualifiers 的重载决议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25170013/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com