Во время работы с перегруженными функциями перегрузки я получаю разные результаты от 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"
.
Я хотел бы узнать, какой компилятор --if любой - делает правильные вещи, и каковы соответствующие стандартные пьесы в игре.
Примечание. Причина, по которой это действительно имеет значение, заключается в том, что реальный код объявляет как const-квалифицированные функции как constexpr
. Конечно, для std::cout
нет вывода, а std::move
используется static_cast
, поэтому они являются допустимыми определениями constexpr
. И поскольку в С++ 11 constexpr
по-прежнему подразумевается const
, перегрузка, прокомментированная в примере кода, не может быть предоставлена, поскольку она переопределяет переопределенную const-переоценку rvalue.