2017-02-03 16 views
3

В C++, где это доступно, это хорошая практика, чтобы использовать auto для многих переменных, в частности, тип которого известен, но раздражает впечатать:C++ 11 внешняя переменная сфера объявлена ​​авто

weird_template_type<int,char>::subtype::recursive_subtype some_function() { 
    // ... 
} 
// ... 
auto val = some_function(); 

Это также хорошо использовать микрообъекты для объектов RAII, если это имеет смысл, например для блокировки:

some_setup_code(); 
int val; 
{ 
    lock_guard<mutex> lk(mut); 
    val = read_shared_memory(); 
} 
do_something(val); 

Есть ли способ смешать эти две идиомы, например. когда ваш код чтения общей памяти возвращает странный тип?

Очевидная версия не работает:

auto val; 
{ 
    lock_guard<mutex> lk(mut); 
    val = read_shared_memory(); 
} 
do_something(val); 

Это терпит неудачу во время компиляции из-за auto переменного без инициализатора.

Аналогично, вы не можете объявить переменную внутри блока с областью действия, иначе она не будет доступна позже.

Единственные непосредственные параметры, которые я вижу, - это 1. введите явно объявление переменной (bleah) или 2. используйте auto с некоторым другим выражением, которое, как известно, имеет тот же тип (не улучшение). Есть ли другой способ?

+0

Может 'decltype()'? – HolyBlackCat

+1

'auto val = (lock_guard (mut), read_shared_memory()); do_something (val); ' – cpplearner

+0

Я хочу отметить, что в большинстве случаев открытие новой области в середине« реальной »области для целей блокировки указывает на проблему с дизайном. вы должны подумать, почему это то, что вы делаете – ZivS

ответ

15

В основном, речь идет о сложной переменной инициализации. Типичным решением является использование лямбда:

auto val = [&]() { 
    lock_guard<mutex> lk(mut); 
    return read_shared_memory(); 
}(); 
+0

Это то, что я уже делал в прошлом, но я думал, что это может быть слишком запутанным для будущих сопровождающих. Откуда вы знаете, что это «типичное» решение? –

+0

Разработчики JS назвали бы это IIFE; это сразу мне знакомо из этого контекста. Не знаете, сколько там перекрытий, но нет путаницы на моем конце. –

+3

@KyleStrand: Вы все еще можете использовать регулярную функцию. Это более старая школа, но лучше для повторного использования. – Jarod42

8

Вы можете рассмотреть

decltype(read_shared_memory()) val; 
{ 
    lock_guard<mutex> lk(mut); 
    val = read_shared_memory(); 
} 
do_something(val); 

, хотя это не обязательно менее многословным.

+0

Нарушает СУХИЕ, лучшие решения существуют ... не используют. :) – GManNickG

+0

Нарушения DRY в сторону, это решение требует, чтобы тип, который вы инициализируете, может быть сконфигурирован по умолчанию. –

+0

@GManNickG О, я согласен, это не самый чистый. Но представьте, что у нас есть более одной переменной, чтобы установить, тогда лямбда тоже выглядела бы неплохо. (Кстати, мне лично нравится ** ** cpplearner ** помещать комментарии :) :) – AlexD

3

Вы можете создать вспомогательную функцию для этого:

int read_shared_int_memory(std::mutex &mut); 
{ 
    std::lock_guard<std::mutex> lock(mut); 
    return read_shared_memory(); 
} 

, а затем просто:

auto val = read_shared_int_memory(mut);