operator<< for templated subclass?

Discussion in 'C++' started by Guenther Brunthaler, Sep 30, 2003.

  1. Hi template specialists,

    I have a problem with the code listed below.

    What I wanted to do is defining an operator<< that is able to output
    a 'matrix<ELEMENT_T, INDEX_T>::subrange' object
    into a 'std::basic_ostream<charT, traits>'.

    For some reason, it does not work. The compiler always complains:

    Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
    te.cpp:
    Error E2094 test.cpp: 'operator<<' not implemented in type
    'std::eek:stream' for arguments of type 'matrix<double,unsigned
    int>::subrange' in function main(int,char * *)
    *** 1 errors in Compile ***

    The INTEL compiler gives a similar error.

    On the other hand, MSVC 7 compiles without any warnings.

    So - which of the compilers are correct?

    And does anyone have an idea what there might be wrong with the code?

    Note:

    If I change the code to output a
    'matrix<ELEMENT_T, INDEX_T>'
    instead of a
    'matrix<ELEMENT_T, INDEX_T>::subrange'
    then it works perfectly for all compilers!

    Only that this is not what I actually want to do.

    So, please help me if you possibly can!

    ---------snip-----------
    #include <iostream>
    #include <cstdlib>


    template<typename ELEMENT_T, typename INDEX_T>
    struct matrix {
    // I want to output an object of this nested type.
    struct subrange {};
    };

    // This templated global function will not be used
    // due to some reason unknown to me.
    template<
    typename ELEMENT_T, typename INDEX_T, typename charT, typename traits
    >

    std::basic_ostream<charT, traits> &operator<<(
    std::basic_ostream<charT, traits> &os,
    matrix<ELEMENT_T, INDEX_T>::subrange const &range)
    {
    os <<"matrix range";
    return os;
    }

    int main(int, char **) {
    matrix<double, size_t>::subrange x;
    std::cout << x;
    return EXIT_SUCCESS;
    }
    ---------snip-----------

    sincerly,

    Guenther
     
    Guenther Brunthaler, Sep 30, 2003
    #1
    1. Advertising

  2. Guenther Brunthaler

    Attila Feher Guest

    Guenther Brunthaler wrote:
    > std::basic_ostream<charT, traits> &operator<<(
    > std::basic_ostream<charT, traits> &os,
    > matrix<ELEMENT_T, INDEX_T>::subrange const &range)


    typename matrix<ELEMENT_T, INDEX_T>::subrange const &range)

    http://www.cuj.com/documents/s=8464/cuj0308dewhurst/

    --
    Attila aka WW
     
    Attila Feher, Sep 30, 2003
    #2
    1. Advertising

  3. Guenther Brunthaler

    tom_usenet Guest

    On Tue, 30 Sep 2003 10:03:42 GMT, Guenther Brunthaler
    <> wrote:

    >Hi template specialists,
    >
    >I have a problem with the code listed below.
    >
    >What I wanted to do is defining an operator<< that is able to output
    >a 'matrix<ELEMENT_T, INDEX_T>::subrange' object
    >into a 'std::basic_ostream<charT, traits>'.
    >
    >For some reason, it does not work. The compiler always complains:
    >
    >Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
    >te.cpp:
    >Error E2094 test.cpp: 'operator<<' not implemented in type
    >'std::eek:stream' for arguments of type 'matrix<double,unsigned
    >int>::subrange' in function main(int,char * *)
    >*** 1 errors in Compile ***
    >
    >The INTEL compiler gives a similar error.
    >
    >On the other hand, MSVC 7 compiles without any warnings.
    >
    >So - which of the compilers are correct?


    INTEL and Borland. matrix<ELEMENT_T, INDEX_T>::subrange is a
    nondeduced context since it requires template argument deduction of
    the template parameters of a parent type based on the type of a nested
    type. The compiler can't perform this deduction in general, because
    the mapping of subtype onto template parameter types is not in general
    many to one, but many to many.

    >And does anyone have an idea what there might be wrong with the code?
    >
    >Note:
    >
    >If I change the code to output a
    >'matrix<ELEMENT_T, INDEX_T>'
    >instead of a
    >'matrix<ELEMENT_T, INDEX_T>::subrange'
    >then it works perfectly for all compilers!


    Right, since that doesn't require argument deduction from a nested
    type.

    >Only that this is not what I actually want to do.
    >
    >So, please help me if you possibly can!


    This version works:

    #include <iostream>
    #include <cstdlib>

    template<typename ELEMENT_T, typename INDEX_T>
    struct matrix {
    // I want to output an object of this nested type.
    struct subrange
    {
    template<typename charT, typename traits>
    friend std::basic_ostream<charT, traits> &operator<<(
    std::basic_ostream<charT, traits> &os,
    subrange const &range)
    {
    os <<"matrix range";
    return os;
    }
    };
    };

    int main(int, char **) {
    matrix<double, size_t>::subrange x;
    std::cout << x;
    return EXIT_SUCCESS;
    }

    http://www.parashift.com/c -faq-lite/containers-and-templates.html#faq-34.15
    is the inverse of what I've done above - the linker errors have been
    avoided by putting the definition inline. The template argument
    deduction problem has been avoided by making removing the ELEMENT_T
    and INDEX_T template parameters from operator<< so that it doesn't
    have to deduce them.

    When matrix<double, size_t>::subrange is instantiated, the friend
    function will also be injected into the global namespace, hence koenig
    lookup on the operator<< call finds the template and instantiates and
    calls it for <char, char_traits<char> >.

    Tom
     
    tom_usenet, Sep 30, 2003
    #3
  4. Thanks a lot, Tom and Attila!

    tom_usenet wrote:

    > This version works:


    But unfortunately not for C++ Builder. Nor for MSVC. Nor GCC.

    But at least it works for INTEL.

    Nevertheless, thanks to you now I know at least what the problem was!

    The fact that so many C++ Compiler still do not comply with the C++
    standard is a different story anyway ;-)


    sincerly,

    Guenther

    (Note: If you want to reply via e-mail, please remove the
    substrings "nospam_" and "_dontspam" from my address.)
     
    Guenther Brunthaler, Oct 1, 2003
    #4
  5. Guenther Brunthaler

    tom_usenet Guest

    On Wed, 01 Oct 2003 03:57:08 GMT, Guenther Brunthaler
    <> wrote:

    >Thanks a lot, Tom and Attila!
    >
    >tom_usenet wrote:
    >
    >> This version works:

    >
    >But unfortunately not for C++ Builder. Nor for MSVC. Nor GCC.
    >
    >But at least it works for INTEL.
    >
    >Nevertheless, thanks to you now I know at least what the problem was!
    >
    >The fact that so many C++ Compiler still do not comply with the C++
    >standard is a different story anyway ;-)


    GCC 3.2 is fine with it, as is MSVC7.1 (2003). Time to upgrade!

    Tom
     
    tom_usenet, Oct 1, 2003
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. jstorta
    Replies:
    3
    Views:
    458
    jstorta
    Feb 20, 2006
  2. Guenther Brunthaler

    operator<< for templated subclass?

    Guenther Brunthaler, Sep 30, 2003, in forum: C++
    Replies:
    0
    Views:
    342
    Guenther Brunthaler
    Sep 30, 2003
  3. S.Volkov
    Replies:
    2
    Views:
    236
    S.Volkov
    Mar 12, 2006
  4. Trans
    Replies:
    8
    Views:
    341
    Robert Klemme
    Oct 23, 2008
  5. Fab

    Subclass of subclass

    Fab, Aug 9, 2012, in forum: C++
    Replies:
    0
    Views:
    411
Loading...

Share This Page