Возвращаемый адрес локальной переменной или временный при использовании возвращаемого значения C ++ 0x decltype - PullRequest
3 голосов
/ 01 июля 2010

Изменить:

Это действительно ошибка в компиляторе, я открыл дефект и получил следующий ответ.

Привет Мотти,
Спасибо за отправку этого вопроса. Как отмечалось в сообщении stackoverflow, это ошибка в нашей реализации decltype. К сожалению, мы не можем исправить эту ошибку в следующей версии Visual Studio, так как код относительно необычен, и мы особенно ограничены в ресурсах.

Следует оригинальный вопрос


Я играю с C ++ 0x в VS10 и столкнулся со следующей проблемой.

std::map<int, int> map()
{
    return std::map<int, int>();
}

template <class F>
auto call(F f) -> decltype(f())
{       
    auto ret = f();
    return ret;
}

void check() 
{
    auto m = call(map); 
}

Я получаю следующее предупреждение:

предупреждение C4172: возврат адреса локальной или временной переменной

Однако, когда я изменяю прототип call на старый стиль:

std::map<int, int> call(F f)

Это нормально, это также нормально, когда call не является функцией шаблона (даже при использовании выведенных типов возврата).

Если я посмотрю на тип ret, то это std::map<int, int> (без ссылок или указателей).

Это ошибка в VS10 или я что-то упустил.

1 Ответ

3 голосов
/ 07 августа 2010

call(map); неявно преобразует карту в указатель на функцию, чтобы сделать функцию:

auto call( std::map<int,int>(*f)() ) -> decltype(f())

Похоже, VC10 не соответствует C ++ 0x FCD для decltype, который говорит:

Тип, обозначаемый decltype (e), определяется следующим образом:

  • , если e является выражением id без скобок или доступом к члену класса [snip, isn't]

  • в противном случае, если e является вызовом функции (5.2.2) или [snip], decltype (e) является типом возврата статически выбранной функции;

  • в противном случае, если e является l-значением, decltype (e) - это T &, где T - тип e;

  • в противном случае, decltype (e)это тип e.

5.2.2 проясняет, что вызов через указатель функции является «вызовом функции», поэтому decltype(f()) должно быть std::map<int,int>.Вместо этого он обрабатывает f () как lvalue-эспрессию с результатом std::map<int,int> &.Тип ret выводится правильно, но он возвращается в ссылку с помощью возврата.

Эта ошибка не отображается, когда вы используете выражение функции вместо выражения указателя функции, decltype(map()) правильнорезультаты в std::map<int,int>.

...