2016-10-10 2 views
2

С введением возвращаемого типа auto в C++ 14 существует ли реальная ситуация, требующая возврата типа возврата или полностью устаревшая в C++ 14 и 17?Обратный тип возврата в C++ 14

+0

Помимо сказанного уже, trailing return-type также позволяет использовать 'this' в возвращаемых типах. – erip

ответ

8

Рассмотрим ...

auto f(int x) 
{ 
    if (x == 2) 
     return 3; 
    return 2.1; 
} 

... это имеет неоднозначный тип возвращаемого значения - int или double. Явный тип возвращаемого значения - как префикс, так и трейлинг - может устранить его и направить аргумент return на возвращаемый тип.

Завершающие возвращаемые типы специально также полезны, если вы хотите использовать decltype, sizeof и т.д. на некоторые аргументы:

auto f(int x) -> decltype(g(x)) 
{ 
    if (x == 2) 
     return g(x); 
    return 2; 
} 
+0

Этот последний пример выглядит странно. Чтобы выяснить тип возврата 'f', нужно знать тип возврата' f'. Не кажется полезным и [gcc не нравится] (http://ideone.com/4eDK25). – nwp

+1

@mwp: ahhh .. Я хотел бы сделать их разными функциями - спасибо, что указали это. –

+0

@Tony D: не могли бы вы отредактировать свой ответ и сделать его более понятным. Я не понял, и я не смог применить ваш пример. – Shadi

9

Обратный тип возврата дает вам поддержку SFINAE. Выведенные типы возврата никогда не вызывают ошибки на ранней стадии, чтобы быть простой заменой.

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

2

Помимо где вы должны использовать его (и другие ответы здесь дают отличные примеры) , вы можете использовать его для ясности, для явного указания того, что возвращает функция. Это очень важно, если вы осознаете (надеюсь, довольно скоро), что чтение кода по крайней мере так же важно, как и его запись.

считают:

auto split(gsl::cstring_span str) 
{ 
    ... 
    ... 
    auto tokens = std::vector<gsl::cstring_span>(); 
    ... 
    ... 
    for (...) { 
     ... 
     ... 
     ... 
    } 
    ... 
    return tokens; 
} 

против:

auto split(gsl::cstring_span str) -> std::vector<gsl::cstring_span>(); 
{ 
    ... doesn't even matter 
} 

не следует искать в реализации, чтобы увидеть, что договор о функции. Вероятно, я мог бы догадаться, каков тип возврата, посмотрев на первый пример, но такие предположения опасны в программировании. Я должен был бы сканировать реализацию, чтобы быть уверенным в том, что получаю, когда вызываю функцию. Во втором примере я четко сформулировал интерфейс. Я не забочусь о реализации, поскольку имя самоочевидно, и поэтому мне не нужно вообще искать определение.

Далее рассмотрим этот даже худший пример. Позволяет узнать, что эта функция возвращает:

auto split(const char* str) 
{ 
    return split(gsl::cstring_span(str)); 
} 

Хорошо, теперь поиск этой перегрузки:

auto split(gsl::cstring_span str) 
{ 
    return split_impl(str); 
} 

Окей ..., теперь давайте следовать, что:

auto split_impl(gsl::cstring_span str) 
{ 
    return split_impl(str, ::isspace); 
} 

Ты е ** Прикалываешься.

Так что я надеюсь, что вы видите точку.

Я не говорю, что всегда использую явный тип возвращаемого значения, я говорю, считая, что знание типа возврата должно быть быстрым с простым взглядом на функцию. Иногда для однострочных, которые можно обнаружить из тела. Иногда его можно безопасно угадать от имени (например, is_empty() явно возвращает bool). В других случаях вам нужно явно называть его.Сделайте жизнь разработчика, который позже использует ваш код, тем более, что в конечном итоге это неизбежно будет вам.