2016-04-04 7 views
-1

Wenn der folgende Code dann innerhalb eines Namensraumes platziert ist seine nicht funktioniert, aber es ist ohne Namespace arbeiten gut ...Warum Typ Traits funktioniert nicht innerhalb Namensraum (std :: enable_if) - c 11 ++

template <typename T,typename _F> 
inline typename std::enable_if< is_iterable<T>::value >::type 
for_all_ele(T&& arr,_F&& fn) 
{ 
    for(auto &x:arr) 
     for_all_ele(x,fn); 

} 

template <typename T,typename _F> 
inline typename std::enable_if< not is_iterable<T>::value >::type 
for_all_ele(T&& x,_F&& fn) 
{ 
    fn(x); 
} 

is_iterable wird darüber definiert ...

der vollständige Code ist hier: http://ideone.com/goJ0Zf

Bis jetzt alles, was ich ist die Template-Spezialisierung von ‚for_all_ele‘ für skalare Daten innerhalb Namensraum finden kann, wird nicht erkannt .. .

+1

Bitte füge einen [MCVE] in deine Frage ein, auch wenn einer im Link ist. Das bedeutet, den Code in der Verbindung zu nehmen und die Teile zu entfernen, die keine Rolle spielen. Beachten Sie, dass der Code * über * innerhalb und außerhalb eines Namespace funktioniert (in dem es nichts tut). – Yakk

Antwort

2

Ihre Rekursion funktioniert, wenn sie über Koenig Lookup (alias ADL, auch bekannt als Argument Dependent Lookup) gefunden wird und nicht wenn sie nicht so gefunden wird.

Dieser Aufruf:

{ 
    for(auto &x:arr) 
    for_all_ele(x,fn); 
} 

nicht später sieht erklärt for_all_ele, es sei denn, eines x oder fn findet es über ADL. Wenn es sich nicht in einem Namespace befindet, befindet sich das Lambda, das Sie als fn übergeben, im selben (Root-) Namespace wie Ihre for_all_ele-Funktion. So ist es gefunden.

Wenn for_all_ele in einem Namespace ist, funktioniert es nicht, da das Lambda in einem anderen Namespace ist.

Es gibt drei Ansätze.

Zuerst können Sie es weiterleiten.

Zweitens können Sie eine Umbruchfunktion erstellen. Es instanziiert dann einen Spielzeugtyp (struct toy_tag{};) und übergibt es zusammen mit den anderen Argumenten an die for_all_ele_impl, die die toy_tag weitergeben, wenn sie recurse.

Drittens können Sie einfach den rekursiven Fall nach dem Abschluss Fall bewegen: https://ideone.com/17h75Q

template <class T, class F> 
inline typename std::enable_if< is_iterable<T>::value >::type 
for_all_ele(T&& arr,F&& f) 
{ 
    for(auto&&x:arr) 
    for_all_ele(decltype(x)(x),f); 
} 

template <class T, class F> 
inline typename std::enable_if< 
    !is_iterable<T>::value 
>::type 
for_all_ele(T&& t,F&& f) { 
    std::forward<F>(f)(std::forward<T>(t)); 
} 

I umbenannt Ihre _F-F, wie der Name _F durch den Standard in allen Kontexten reserviert ist. Ich habe auch das Funktionsobjekt perfekt weitergeleitet, weil ich so bin. Und ich habe eine perfekte Weiterleitung gemacht, der Code fehlte.

+0

'nicht' :)' T und x, F und fn': P –

+0

@ T.C. von OP geerbt. Aber ya, nur bearbeitet, um konventioneller gemacht zu werden. – Yakk

+0

Gut Danke für Ihre Ansätze, Die dritte funktionierte sehr gut für mich, ich bin mir nicht sicher über den zweiten Ansatz, aber ich kann nicht die Vorwärtsdeklaration Ansatz IMPLEMENT, gibt es mir gleichen Fehler wie zuvor ... Hier ist mein Versuch ... [http://ideone.com/x39cMV](http://ideone.com/x39cMV) –

Verwandte Themen