При работе с перегрузками функций с указанием ссылки я получаю разные результаты от GCC (4.8.1) и Clang (2.9 и trunk). Рассмотрим следующий код:
#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
нет вывода, а вместо std::move
используется static_cast
, так что они являются действительными constexpr
определениями. И поскольку в C ++ 11 constexpr
по-прежнему подразумевается const
, перегрузка, закомментированная в примере кода, не может быть предоставлена, так как она переопределит перегрузку rvalue с константой.