2013-05-15 12 views
14

Il modificatore noexcept può essere applicato a un'espressione lambda? Se é cosi, come?Utilizzo di noexcept come modificatore lambda o vincolo parametro

È possibile impostare noexcept un vincolo su un argomento di funzione? Ad esempio, qualcosa di simile nel seguente codice, in cui il significato è che la funzione di callback deve essere noexcept?

//probably not valid code - I'm just trying to express the idea 
void f_async(std::function<void (int) noexcept> callback) noexcept 
{ 
    ... 
} 

Questo può quasi essere realizzato con il seguente codice, ma mi chiedo se c'è un modo per utilizzare qualcosa come il sopra alternativa.

void f_async(std::function<void (int)> callback) 
    noexcept(callback(std::declval<int>())) 
{ 
    ... 
} 

Il problema qui, naturalmente, è che f_async può essere noexcept(false) se il callback è noexcept(false) - voglio fare una dichiarazione forte che f_async è semprenoexcept, che significa che è richiamabile solo se si utilizza un callback noexcept.

risposta

16

Può il modificatore noexcept essere applicato a un'espressione lambda? Se é cosi, come?

Aggiungere noexcept dopo la parentesi:

[](Args args) noexcept { ... } 

Può noexcept essere fatto un vincolo su un argomento di funzione?

Sì, uso enable_if:

template <typename F> 
auto f_async(const F& func) noexcept 
     -> typename std::enable_if<noexcept(func(0))>::type { 
    func(0); 
} 

int main() { 
    f_async([](int x) noexcept {}); 
    f_async([](int x) {}); // <- this line won't compile 
} 

Tuttavia, questo metodo non può lavorare direttamente in g ++ 4.7 (funziona in clang ++ 3.2), perché non può storpiare ancora noexcept espressione:

3.cpp: 5: 6: sorry, non implementato: pressare noexcept_expr

Si potrebbe aggirare utilizzando una struttura involucro:

template <typename F, typename... Args> 
struct EnableIfNoexcept 
     : std::enable_if<noexcept(std::declval<F>()(std::declval<Args>()...))> {}; 

template <typename F> 
auto f_async(const F& func) noexcept -> typename EnableIfNoexcept<F, int>::type { 
    func(0); 
} 
+0

Interessante - Non ho davvero visto questo 'std :: enable_if' prima. Sembra promettente. –

+1

Bel tentativo, ma non funziona quando si passa la funzione free a f_async in clang 3.5. –

+0

http://rextester.com/RDIX55455 –

4

quanto riguarda la prima domanda:

Può il modificatore noexcept essere applicato a un'espressione lambda? Se é cosi, come?

Sì, basta aggiungere la specifica eccezione dopo la lista dei parametri:

[] (int i) noexcept { return i * 1; }; 
//   ^^^^^^^^ 

Per il paragrafo 5.1.2/5 del C++ 11 standard:

Il tipo di chiusura per un'espressione lambda ha un operatore di chiamata di funzione inline pubblica (13.5.4) i cui parametri e tipo di ritorno sono descritti rispettivamente dal tipo parametro-dichiarazione-clausola e trailingreturn-espressione di lambda-expression, rispettivamente . Questo operatore di chiamata di funzione è dichiarato const (9.3.1) se e solo se la clausola-dichiarazione-clausola espressione lambda non è seguita da mutabile. Non è né virtuale né dichiarato volatile. Gli argomenti predefiniti (8.3.6) non devono essere specificati nella clausola-dichiarazione-parametro di un lambda-dichiaratore. Qualsiasi specifica di eccezione specificata su un'espressione lambda si applica alla corrispondente funzione operatore di chiamata. Un attributo-specificatore-seq in un lambda-dichiaratore appartiene al tipo del corrispondente operatore di chiamata di funzione . [Nota: i nomi a cui si fa riferimento nel lambda-dichiaratore vengono cercati nel contesto in in cui appare l'espressione lambda. -end nota]

Problemi correlati