2014-05-21 17 views
6

Testen mit g ++ 4.9 und Klirren 3.4, warum dieser Code nicht kompilieren:rekursive noexcept Spezifikation

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); 
} 

Aber dieser Code tut:

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); 
} 

Die f_helper Funktion muss nicht definiert werden, Es muss nur der korrekte Rückgabetyp angegeben werden, der in diesem Fall über declltype angegeben wird.

Der erste Code kompiliert auch für 1 oder 2 Argumente, aber sobald ich versuche, es mit 3 oder mehr zu nennen, bekomme ich Fehler über keine übereinstimmenden Funktionen zu nennen. Das Klappern Fehler für die erste Code:

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

Die Version mit dem Helfer [kompiliert nicht] (http://coliru.stacked-crooked.com/a/126cee2269269e96), wenn Sie 4 Parameter an f übergeben. –

Antwort

5

3.3.2/1 Der Punkt der Deklaration für einen Name ist unmittelbar nach seiner vollständigen declarator (Ziffer 8) und vor dessen Initialisierer (falls vorhanden) ...

Ausnahme-Spezifikation ist syntaktisch Teil des declarator. Daher befindet sich der Funktionsname nicht in seiner eigenen Ausnahmespezifikation.

+0

Obwohl ich diese Funktion technisch nicht wirklich rekursiv aufruft, rufe ich eine völlig andere Funktion auf, die von der gleichen Vorlage erzeugt wird, die letztendlich die Definition der Funktion mit einem Argument aufruft. Könnte mir das helfen? –

+1

Der Name dieser Funktionsvorlage ist nicht an dem Punkt enthalten, an dem Sie sie verwenden möchten. –

+0

@DavidStone Ich denke, es kann jedoch über ADL gefunden werden? Dies öffnet die Dinge für einen Hack, wo Sie eine "Template" -Funktionsimplementierung mit einem Dummy-Argument aus demselben 'Namespace' erstellen und die öffentlichkeitswirksame im Hinblick auf diese Implementierung definieren. Unsicher, ob das funktioniert. – Yakk