Problem mit MSVC6: partial template instantiation



  • Ich arbeite an einer plattformunabhängigen Bibliothek, die ausgiebigen Gebrauch von Templates macht. Einige Komponenten redefinieren Templates mittels "partial template instantiation". Dies funktioniert mit allen meinen Compilern (Borland BCB5, GNU g++3.3 und Intel icc 😎 prächtig, nur der "Marktführer" hat Probleme damit. Ich habe hier die Version MSVC6, über MSVC7 oder eventuelle neuere kann ich mangels Erfahrung nichts sagen.

    Einen Teilerfolg habe ich mit der Redefinition einzelner Methoden erreicht, allerdings ist das mühsam, da für jeden Typ nötig.

    Hat jemand eine bessere Idee? Das Hauptproblem liegt derzeit darin, daß "return void" nicht compiliert.

    Hier ein komplett funktionierendes Beispiel:

    #include <iostream>
    
    #ifdef _MSC_VER
    #define PARTIAL_BUG
    #endif
    
    template <typename R,   // return
              typename I>   // input
    class Outer
    {
      public:
    
    };
    
    template <typename R,   // return
              typename I>   // input
    class Base
    {
      public:
    
        Base(Outer<R,I> *outer)
        {}
    
        virtual R invoke( const I &input ) = 0;
    };
    
    template <typename R,   // return
              typename I>   // input
    class Derived : public Base<R, I>
    {
      public:
    
        Derived(Outer<R,I> *outer)
          : Base<R, I>(outer)
        {}
    
        R invoke( const I &input )
        {
          std::cout << "Derived<R,I>\n";
          return R();
        }
    };
    
    #ifndef PARTIAL_BUG
    
    template <typename I>   // input
    class Derived<void, I> : public Base<void, I>
    {
      public:
    
        Derived(Outer<void,I> *outer)
         : Base<void, I>(outer)
        {}
    
        void invoke( const I &input )
        {
          std::cout << "Derived<void,I>\n";
          // void return
        }
    };
    
    #else
    
    void Derived<void, int>::invoke(const &)
    {
      std::cout << "special Derived<void,I>\n";
      return;
    }
    
    #endif
    
    int main()
    {
      Derived<int, int> dii(0);
      int i = dii.invoke(1);
    
      Derived<void, int> dvi(0);
      dvi.invoke(1);
    
      return 0;
    }
    


  • ewi schrieb:

    Dies funktioniert mit allen meinen Compilern (Borland BCB5, GNU g++3.3 und Intel icc 😎 prächtig, nur der "Marktführer" hat Probleme damit.

    Ziemlich unfair den g++3.3 mit dem MSVC6 zu vergleichen, findest du nicht? Liegen immerhin einige Jahre dazwischen. Ums kurz zu machen: Der MSVC6 kann es noch nicht.



  • Ziemlich unfair den g++3.3 mit dem MSVC6

    Dass der Vergleich nicht ganz fair ist mag schon sein, aber BCB5 stammt aus dem selben Zeitraum und hat keine Probleme damit, ebenso mit weiteren ähnlichen Fällen. Ich habe einfach den (subjektiven) Eindruck, daß MS nicht mehr implementiert hat, als für die MFC nötig war.

    Da MSVC6 noch recht in Gebrauch zu sein scheint, war mir an einer Lösung trotzdem gelegen. Kannst du was zu MSVC7 und eventuellen anderen sagen? Das Beispiel sollte, wie gesagt, je nach #define überall funktionieren.

    Nachtrag:
    Der Vergleich hat mich dann doch noch genauer interessiert und ich habe meine BSD-Kiste rausgezogen. Die dient eigentlich nur noch dem Zweck, meinen ältesten Compiler zu beherbergen, einen g++ 2.95. Hier das Log:

    $ uname -a
    OpenBSD merkur 3.1 GENERIC#59 i386
    $ g++ --version
    2.95.3
    $ make
    g++ msvc-partial.cpp -o msvc-partial.gcc
    $ ./msvc-partial.gcc
    Derived<R,I>
    Derived<void,I>
    $
    

    Wie man sieht, hat der ebenfalls keine Probleme obwohl er mindestens so alt ist wie MSVC6.



  • Das VS.NET 7.1 (2003) kann templates richtig. Das 6er und 7.0 (2002) kannst du in der Hinsicht vergessen.



  • Frag lieber im C++ Unterforum. Dort ist ein Experte "HumeSikkins", der dir da mehr zu sagen kann. Wenn es einen Workaround dafür gibt, dann hat er ihn. 😉



  • dEUs schrieb:

    Das 6er und 7.0 (2002) kannst du in der Hinsicht vergessen.

    Schade, ich hatte etwas mehr erhofft, aber danke für alle Antworten 😉


Anmelden zum Antworten