2017-05-24 5 views
1

Ich frage mich, wie die when Spezialisierung funktioniert, wenn es keine Fallbasis für den boost::hana::when<false> Fall gibt.boost :: hana tag_der Implementierung

boost::hana::tag_of Umsetzung:

template<bool condition> 
struct when; // forward declaration only 

template<typename T, typename = void> 
struct tag_of; 

template<typename T, typename> 
struct tag_of : tag_of<T, when<true> > 
{}; 

template<typename T, bool condition> 
struct tag_of<T, when<condition> > 
{ 
    using type = T; 
}; 

und ein Testbeispiel:

struct my_tag {}; 
struct my_tag2 {}; 

namespace boost { 
    namespace hana { 

     template<class T> 
     struct tag_of<T, when<std::is_same<T, int>{}()> > 
     { 
      using type = my_tag; 
     }; 

     template<class T> 
     struct tag_of<T, when<std::is_same<T, unsigned>{}()> > 
     { 
      using type = my_tag2; 
     }; 
    } 
} 

int main() 
{ 
    using type = boost::hana::tag_of<int>::type; 
    std::cout << std::is_same<type, my_tag>{} << std::endl; 
} 

und ich frage mich, warum std::is_same<T, int>{}() (oder mit ::value, die gleich ist), ist eine spezialisierte Teil Spezialisierung als std::is_same<T, unsigned>{}(), und warum, wenn die Bedingung in beiden Fällen falsch ist, ist spezialisierter.

Ich habe viele Metafunktionen und arbeiten mit Spezialisierungen und Parameter-Packs und die Art, aber in diesem Fall gibt es etwas, das ich nicht sehe.

Die Sache ist, dass ich sehe nicht, warum der true oder false Wert der when Vorlage Materie kann, wenn es für den false Fall keine Default-Implementierung ist.

Antwort

1

und ich frage mich, warum std::is_same<T, int>{}() (oder mit ::value, die gleich ist), ist eine spezialisierte Teil Spezialisierung als std::is_same<T, unsigned>{}(), und warum, wenn die Bedingung für beide Fall falsch ist, when<condition> ist mehr spezialisiert.

Es ist nicht spezialisierter. Sie sind einfach nie beide brauchbare Spezialisierungen. Lassen Sie uns durchgehen, was passiert, wenn wir versuchen, hana::tag_of<int> instanziieren.

  1. Füllen Sie die Standardvorlagenargumente aus. In diesem Fall ist der zweite Vorlagenparameter standardmäßig void, also haben wir wirklich hana::tag_of<int, void>.
  2. Überlegen Sie, welche Teilspezialisierungen machbar sind. In diesem Fall sind keine von ihnen lebensfähig - unser Typ (int) ist keine Referenz oder cv-qualifiziert und es ist keine Art von when<condition>. Da keine der Spezialisierungen praktikabel ist, instanziieren wir die primäre Vorlage.
  3. Die primäre tag_of<T, void> erbt von tag_of<T, when<true>>. Jetzt müssen wir diesen zweiten Typ instantiieren, was bedeutet, dass wir Schritt 2 wiederholen. Jetzt
  4. zwei verschiedene Spezialisierungen sind lebensfähig:

    // from hana's core 
    template <typename T, bool condition> 
    struct tag_of<T, when<condition>> 
    
    // yours 
    template <typename T> 
    struct tag_of<T, when<std::is_same<T, int>{}()>> 
    

    Beachten Sie, dass Ihre anderen Spezialisierung nicht rentabel ist - weil std::is_same<T, unsigned>{}false ist und wir versuchen when<true> übereinstimmen.

  5. Zwischen diesen beiden Spezialisierungen ist Ihre Spezialisierung, wenn wir die partiellen Ordnungsregeln durchlaufen - also ausgewählt und instanziiert.

Daher ist hana::tag_of<int>::typehana::tag_of<int, void>::type ist hana::tag_of<int, when<true>>::type ist hana::tag_of<int, when<std::is_same<T, int>{}()>>::typemy_tag ist.


Die Sache ist, dass ich sehe nicht, warum der true oder false Wert der als Vorlage Materie kann, wenn es für den false Fall keine Default-Implementierung ist.

Das oben genannte zeigt hoffentlich, warum es wichtig ist. Wir instanziieren when<false> nicht direkt, aber Sie könnten eine Spezialisierung schreiben, die in when<false> (wie Ihre Spezialisierung when<std::is_same<T, unsigned>{}()>) ersetzt.

und warum, wenn die Bedingung false für beide Fälle ist, ist when<condition> mehr spezialisiert.

Da wir when<true> sind instanziiert wird, diese Spezialisierungen, deren Zustand false werden einfach aus dem Kandidatensatz ausgeschlossen. Die Liste der praktikablen Spezialisierung wird nur auf diejenige reduziert, die Hana direkt anbietet. Es ist nicht "spezialisierter" - es ist nur lebensfähig.


auch erwähnenswert, dass tag_of Sie mehrere Möglichkeiten zur Spezialisierung gibt. Sie können entweder eine boolesche Bedingung odervoid_t verwenden. Oder Sie könnten nur auf oberster Ebene spezialisiert:

template <> 
struct tag_of<int, void> { 
    using type = my_tag; 
}; 

Das würde Kurzschluss im Schritt # 2 oben, das Überspringen alle anderen Instanzen.

+0

Es ist unglaublich schön. Vielen Dank. –