Problem Streamoperator und Klassentemplate substruktur



  • Hi,
    hoffe jemand kann mir einen Tip geben.

    Ich habe ein Klassentemplate, das ein Typedef enthält, zu dem ich einen Streamoperator bereitstellen möchte.
    Leider matcht er den operator aus irgend welchen Gründen nicht und gibt mir immer den Fehler "binary '<<': no operator found ...

    #include <iostream>
    #include <array>
    
    template <int DIM>
    class Test
    {
    public:
      typedef std::array<int, DIM> A;
    };
    
    template< int DIM>
    std::ostream& operator<<( std::ostream& str, const typename Test<DIM>::A& rm )
    {
      str << rm.size();
      return str;
    }
    
    // [...]
    Test< 5>::A a;
    std::cout << a;
    // [...]
    

    Compiler ist MSVC10

    Hat jemand einen Tip?

    Gruß
    Vlad


  • Mod

    typename Test<DIM>::A
    

    ist kein Kontext, in dem DIM deduziert werden könnte.



  • camper schrieb:

    typename Test<DIM>::A
    

    ist kein Kontext, in dem DIM deduziert werden könnte.

    das heißt? was muss ich tun, damit es funktioniert?


  • Mod

    vlad_tepesch schrieb:

    camper schrieb:

    typename Test<DIM>::A
    

    ist kein Kontext, in dem DIM deduziert werden könnte.

    das heißt?

    Um die aufzurufende Funktion zu bestimmen, muss der Compiler aus dem übergebenen Argument den passenden Templateparamter bestimmen (deduzieren). Das ist bei einem Bezeichner dieser Form grundsätzlich nicht möglich.
    z.B.

    #include <iostream>
    #include <array>
    
    template <int DIM>
    class Test
    {
    public:
      typedef std::array<int, DIM> A;
    };
    
    template< int DIM>
    std::ostream& operator<<( std::ostream& str, const typename Test<DIM>::A& rm )
    {
      str << rm.size();
      return str;
    }
    
    template <>
    class Test<0>
    {
    public:
      typedef std::array<int, 5> A;
    };
    
    // [...]
    Test< 5>::A a;
    std::cout << a;  // DIM==5 oder DIM==0 ?
    // [...]
    

    (selbst wenn es Spezialisierung nicht gäbe, wäre eine solche Deduktion im allgemeinen Fall unmöglich).

    vlad_tepesch schrieb:

    was muss ich tun, damit es funktioniert?

    Das kommt ein bisschen darauf an, was und warum du so etwas tun willst.
    Handelte es sich nicht um ein typedef sondern um einen in der Klasse definierten Typ, könnten Friendfunktionen genutzt werden, die per ADL gefunden werden.

    Bei einem einfachen typedef ist der betreffende Typ dagegen in keiner Weise mit deinem Template assoziert. Dann bleibt wahrscheinlich nur die Verwendung eines sehr allgemeinen Templates, das mittels Prädikates dann geeignet eingeschränkt wird

    template<typename T>
    typename std::enable_if<is_Test_A<T>::value,std::ostream>::type& operator<<( std::ostream& str, const T& rm )
    {
        const int DIM = get_dim<T>::value;
    

    is_Test_A und get_dim müsstest du dann selbst schreiben.


Anmelden zum Antworten