Specializzazione dei modelli basata sulla class eredita

Voglio rendere questo specializzato senza cambiare main. È ansible specializzare qualcosa in base alla sua class base? Lo spero.

-modificare-

Avrò diverse classi che ereditano da SomeTag. Non voglio scrivere la stessa specializzazione per ognuno di essi.

class SomeTag {}; class InheritSomeTag : public SomeTag {}; template  struct MyClass { }; template  struct MyClass { typedef int isSpecialized; }; int main() { MyClass::isSpecialized test1; //ok MyClass::isSpecialized test2; //how do i make this specialized w/o changing main() return 0; } 

    Questo articolo descrive un trucco chiaro: http://www.gotw.ca/publications/mxc++-item-4.htm

    Ecco l’idea di base. Per prima cosa è necessaria una class IsDerivedFrom (che fornisce il runtime e il controllo in fase di compilazione):

     template class IsDerivedFrom { class No { }; class Yes { No no[3]; }; static Yes Test( B* ); // not defined static No Test( ... ); // not defined static void Constraints(D* p) { B* pb = p; pb = p; } public: enum { Is = sizeof(Test(static_cast(0))) == sizeof(Yes) }; IsDerivedFrom() { void(*p)(D*) = Constraints; } }; 

    Quindi la tua MyClass ha bisogno di un’implementazione potenzialmente specializzata:

     template class MyClassImpl { // general case: T is not derived from SomeTag }; template class MyClassImpl { // T is derived from SomeTag public: typedef int isSpecialized; }; 

    e MyClass sembra davvero:

     template class MyClass: public MyClassImpl::Is> { }; 

    Allora il tuo principale andrà bene così com’è:

     int main() { MyClass::isSpecialized test1; //ok MyClass::isSpecialized test2; //ok also return 0; } 

    Bene, l’articolo nella risposta sopra è apparso nel febbraio 2002. Mentre funziona, oggi sappiamo che ci sono modi migliori. In alternativa, puoi utilizzare enable_if :

     template struct enable_if { typedef T type; }; template struct enable_if { }; template struct is_same { static bool const value = false; }; template struct is_same { static bool const value = true; }; template struct is_base_of { static D * create_d(); static char (& chk(B *))[1]; static char (& chk(...))[2]; static bool const value = sizeof chk(create_d()) == 1 && !is_same::value; }; struct SomeTag { }; struct InheritSomeTag : SomeTag { }; template struct MyClass { /* T not derived from SomeTag */ }; template struct MyClass::value>::type> { typedef int isSpecialized; }; int main() { MyClass::isSpecialized test1; /* ok */ MyClass::isSpecialized test2; /* ok */ } 

    E la versione breve ora, 2014, usando C ++ – 11:

     #include  struct SomeTag { }; struct InheritSomeTag : SomeTag { }; template::value> struct MyClass { }; template struct MyClass { typedef int isSpecialized; }; int main() { MyClass::isSpecialized test1; /* ok */ MyClass::isSpecialized test2; /* ok */ } 

    Nel tuo caso, l’unico modo che vedo sarebbe quello di specializzare esplicitamente MyClass per InheritSomeTag . Tuttavia, il documento SeqAn propone un meccanismo chiamato “template sublassing” che fa ciò che vuoi – anche se con una syntax di ereditarietà diversa, quindi il codice non è compatibile con la tua funzione main corrente.

     // Base class template  class SomeTag { }; // Type tag, NOT part of the inheritance chain template  struct InheritSomeTag { }; // Derived class, uses type tag template  class SomeTag > : public SomeTag { }; template  struct MyClass { }; template  struct MyClass > { typedef int isSpecialized; }; int main() { MyClass >::isSpecialized test1; //ok MyClass > >::isSpecialized test2; //ok } 

    Questo sicuramente sembra strano ed è molto ingombrante ma consente un vero meccanismo di ereditarietà con funzioni polimorfiche che vengono eseguite in fase di compilazione. Se vuoi vedere questo in azione, dai uno sguardo ad alcuni esempi di SeqAn .

    Detto questo, credo che SeqAn sia un caso speciale e non molte applicazioni potrebbero trarre profitto da questa syntax estremamente difficile (la decifrazione degli errori del compilatore correlati a SeqAn è un vero dolore per * ss!)