2016-04-15 8 views
1

В настоящее время я просматриваю ссылки r-value и переводит семантику, и я вижу странное несоответствие в своих собственных экспериментах по кодированию.При использовании std :: forward, почему я могу вызвать опорную функцию l-value при передаче в r-значении?

Учитывая приведенный ниже код:

#include <iostream> 

using namespace std; 

class X{}; 

void g(X&& t) // A 
{ 
    cout << "Rref call" << endl; 
}  

void g(X& t) // B 
{ 
    cout << "Lref call" << endl; 
}  

template<typename T> 
void f(T&& t) 
{ 
    g(forward<T>(t)); 
} 

int main() 
{ 
    X x; 
    f(x); // 1 
    f(X()); // 2 

    return 0; 
} 

будет генерировать ожидаемый результат здесь:

LRef называют

Rref называют

Однако, если я иду вперед и удалите перегруженную функцию g, которая принимает ссылку на r-значение (обозначенный выше на комментарий линии // А), я получаю следующий результат:

LRef называют

LRef называют

Как это работает вне дома? Почему компилятор не жалуется на вызов g(X& t) при попытке передать в X&&?

+3

Вы используете Visual Studio? Если это так, у него есть [нестандартное расширение] (http://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to-a-temporary-object), чтобы позволяют временным связям с неконстантными ссылками. Он не работает [в этом примере] (http://ideone.com/TcJbJA). –

+0

Джеймс, похоже, именно он. Собирался орехи, пытаясь понять, что происходит. Весьма признателен. – Joefers

ответ

3

Когда вы закомментируете перегрузку g(X&& t), вы используете MSVC extension, что позволяет привязывать значения к значениям const lvalue. Если вы установите уровень предупреждения на /W4, MSVC сообщит вам, что используется нестандартное расширение.

И gcc и clang fail to compile код с этой перегрузкой прокомментирован.

+0

Yup! Использовал Visual Studio, и он с радостью принял это. Благодарю вас. – Joefers

+0

Это одна из самых страшных ошибок в MSVC. И хотя это могло иметь некоторый смысл в те дни, когда не было ссылок на rvalue, теперь это имеет смысл. Они должны были отключить его для кода C++ 11. – SergeyA

+0

@SergeyA Ну, он отключается, если вы компилируете с '/ W4' и'/WX', как и должно быть :) Но я не хочу оправдываться за них, это ужасное расширение. – Praetorian

 Смежные вопросы

  • Нет связанных вопросов^_^