2012-04-10 8 views
1

Das SFINAE Prinzip funktioniert nicht für das, was in Visual Studio wirklich einfach scheint 2010.SFINAE funktioniert nicht auf Visual Studio 2010 für std :: is_pointer

#include <type_traits> 
#include <iostream> 

struct MyStruct 
{ 
    int value; 
    MyStruct(int value = 42) : value(value) { } 
    const int& getInt() const { return value; } 
}; 

template <typename ITER_TYPE> 
auto getIteratorInt(ITER_TYPE iter) -> 
    typename std::enable_if 
    <std::is_pointer<decltype(*iter)>::value, const int&>::type 
{ 
    return (*iter)->getInt(); 
} 

template <typename ITER_TYPE> 
auto getIteratorInt(ITER_TYPE iter) -> 
    typename std::enable_if 
    <!std::is_pointer<decltype(*iter)>::value, const int&>::type 
{ 
    return iter->getInt(); 
} 

int main(void) 
{ 
    MyStruct gloryInt; 
    MyStruct* gloryIntPtr = &gloryInt; 
    std::cout << getIteratorInt(gloryIntPtr) << std::endl; 
    std::cout << getIteratorInt(&gloryIntPtr) << std::endl; 
    return 0; 
} 

Meine Absicht ist es std::enable_if zu verwenden, um die richtige Vorlage zu kompilieren Überlastung nach dem SFINAE-Prinzip. (Die Funktion ohne den vorhandenen Rückgabetyp wird ignoriert, und der andere wird kompiliert.) Auf diese Weise können Sie einen Zeiger oder einen Doppelzeiger auf ein Objekt verwenden, und das direkte Objekt bleibt weiterhin das, worauf zugegriffen wird.

ich folgende Kompilierungsfehler erhalten:

main.cpp(14): error C2039: 'type' : is not a member of 'std::tr1::enable_if<_Test,_Type>' 
      with 
      [ 
       _Test=false, 
       _Type=const int & 
      ] 
main.cpp(17): error C3646: 'type' : unknown override specifier 

Nun, das ist eine wirklich offensichtliche Fehler zu haben, wenn SFINAE nicht verwendet wurde. Gibt es eine Möglichkeit, die beabsichtigte Funktionalität in Visual Studio 2010 zu erhalten?

Antwort

2

Heh, sollte Ihre Profilseite überprüft haben, bevor Sie die andere Antwort aktualisieren.

Der Typ decltype(* iter) bezieht sich auf int const *const &, das ist ein Verweis auf einen Zeiger, kein "bare" Zeiger. Daher gibt std::is_pointer ein unerwartetes Ergebnis zurück. Es gibt zwei Möglichkeiten, dieses Problem zu lösen:

  • Verwenden std::iterator_traits von C++ 03, die ich lieber:

    typename std::iterator_traits<ITER_TYPE>::value_type 
    
  • Verwenden Sie die std::decay metafunction die Referenzen abstreift decltype könnte fügen Sie den Wert widerzuspiegeln Kategorie des Ausdrucks

    typename std::decay< decltype(* iter) >::type 
    
+0

Ja, nein Wenn Sie es erwähnen, wäre die ständige Referenz da. Meine ursprüngliche Lösung war also std :: remove_reference, und es scheint mit GCC zu kompilieren, aber immer noch nicht mit Visual Studio 2010. Die iterator_traits-Lösung funktionierte jedoch. Vielen Dank! – ComplexRobot

+0

Auch ich nehme an, dass der Trailing-Return-Typ nicht mehr notwendig ist. – ComplexRobot