2014-05-21 15 views
6

Test con g ++ 4.9 e clang 3.4, perché questo codice non compilare:ricorsivo specifica noexcept

namespace { 

template<typename T> 
constexpr auto f(T && t) noexcept { 
    return true; 
} 

template<typename T, typename... Ts> 
constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) { 
    return f(ts...); 
} 

} // namespace 

int main() { 
    f(true, 0, 5u); 
} 

Ma questo codice fa:

namespace { 

template<typename T> 
constexpr auto f(T && t) noexcept { 
    return true; 
} 

template<typename T> 
constexpr auto f_helper(T && t) noexcept(noexcept(f(t))) { 
    return f(t); 
} 

template<typename T, typename... Ts> 
constexpr auto f_helper(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) { 
    return f(ts...); 
} 

template<typename T, typename... Ts> 
constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f_helper(ts...))) { 
    return f(ts...); 
} 

} // namespace 

int main() { 
    f(true, 0, 5u); 
} 

La funzione f_helper non deve essere definito, deve semplicemente avere il tipo di ritorno corretto specificato in decltype in quel caso.

Il primo codice viene compilato anche per 1 o 2 argomenti, ma quando provo a chiamarlo con 3 o più, ottengo errori su nessuna funzione di corrispondenza da chiamare. L'errore clang per il primo codice è:

source/main.cpp:9:59: error: call to function 'f' that is neither visible in the template definition nor 
     found by argument-dependent lookup 
     constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) { 
                   ^
source/main.cpp:9:17: note: in instantiation of exception specification for 'f<bool, int, unsigned int>' 
     requested here 
     constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) { 
        ^
source/main.cpp:16:3: note: in instantiation of function template specialization '<anonymous 
     namespace>::f<bool, int, unsigned int>' requested here 
       f(true, 0, 5u); 
       ^
source/main.cpp:9:17: note: 'f' should be declared prior to the call site 
     constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) { 
        ^
1 error generated. 
+0

La versione con l'helper [non viene compilata] (http://coliru.stacked-crooked.com/a/126cee2269269e96) se si passano 4 parametri a f. –

risposta

5

3.3.2/1 il punto di dichiarazione per un nome è immediatamente dopo la sua dichiaratore completa (clausola 8) e prima della sua inizializzazione (se presente) ...

specifica delle eccezioni è sintatticamente parte del dichiaratore. Pertanto, il nome della funzione non è nell'ambito della propria specifica di eccezione.

+0

Anche se tecnicamente non sto chiamando questa funzione in modo ricorsivo, sto chiamando una funzione completamente diversa generata dallo stesso template, che alla fine chiama la definizione della funzione a singolo argomento. Potrebbe aiutarmi? –

+1

Il nome del modello di funzione non è nel campo di applicazione nel punto in cui si sta tentando di utilizzarlo. –

+0

@DavidStone Penso che possa essere trovato tramite ADL comunque? Il che apre le cose a un hack, in cui si crea un'implementazione della funzione 'template' con un argomento dummy dallo stesso' namespace', e si definisce quella pubblica in termini di detta implementazione. Incerto se questo funziona. – Yakk

Problemi correlati