2017-02-03 3 views
3

In C++, wo es verfügbar ist, ist es empfehlenswert, auto für viele Variablen zu verwenden, solche, deren Art insbesondere bekannt, aber ärgerlich tippen:C++ 11 äußere Umfang Variable deklariert Auto

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

Es ist auch gut, Mikro-Scopes für RAII-Objekte zu verwenden, wenn das sinnvoll ist, z zum Verriegeln:

Gibt es eine Möglichkeit, diese beiden Idiome zu mischen, z.B. Wenn Ihr Shared-Memory-Reading-Code einen seltsamen Typ zurückgibt?

Die offensichtliche Version nicht funktioniert:

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

Dies ohne initializer aufgrund einer auto Variable bei der Kompilierung fehlschlägt.

In ähnlicher Weise können Sie die Variable innerhalb des scoped Block nicht erklären, sonst ist es nicht später verfügbar. Die einzigen unmittelbaren Optionen, die ich sehen kann, sind 1. Geben Sie die Variablendeklaration explizit (bleah) aus, oder 2. Verwenden Sie mit einem anderen Ausdruck, von dem Sie wissen, dass er vom selben Typ ist (keine Verbesserung). Gibt es einen anderen Weg?

+0

Vielleicht 'decltype()'? – HolyBlackCat

+1

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

+0

ich, dass Sie einen neuen Bereich in der Mitte eines„echten“Raum für Verriegeln Öffnung zeigt ein Designproblem in den meisten Fällen darauf hin will. Sie sollten überlegen, warum Sie das tun – ZivS

Antwort

15

Im Grunde, was du redest ist komplex Variableninitialisierung. Die typische Lösung ist eine Lambda zu verwenden:

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

Das ist etwas, das ich in der Vergangenheit in Betracht gezogen habe, aber ich dachte, es könnte für zukünftige Betreuer zu verwirrend sein. Woher wissen Sie, dass dies die "typische" Lösung ist? –

+0

JS Entwickler würden es ein IIFE nennen; es ist mir aus diesem Kontext sofort vertraut. Ich bin mir nicht sicher, wie viel Überlappung dort ist, aber keine Verwirrung an meinem Ende. –

+3

@KyleStrand: Sie können immer noch normale Funktion verwenden. Was ist mehr Old School, aber besser für die Wiederverwendbarkeit. – Jarod42

8

können Sie

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

betrachten, obwohl es nicht unbedingt weniger ausführlich ist.

+0

Verstößt gegen DRY, bessere Lösungen existieren ... nicht verwenden. :) – GManNickG

+0

Verstöße gegen DRY beiseite, erfordert diese Lösung, dass der Typ, den Sie initialisieren, standardmäßig erstellt werden kann. –

+0

@GManNickG Oh, ich stimme zu, es ist nicht das sauberste. Aber stell dir vor, wir haben mehr als eine Variable zu setzen, dann würde Lambda auch nicht gut aussehen. (BTW, persönlich mag ich die eine ** @ cpplearner ** setzen Sie die Kommentare. :)) – AlexD

3

Sie können eine Hilfsfunktion für das erstellen:

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

und dann einfach wie folgt:

auto val = read_shared_int_memory(mut);