operator<< for templated subclass?

  • Thread starter Guenther Brunthaler
  • Start date
G

Guenther Brunthaler

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 traitsstd::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
 
T

tom_usenet

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
 
G

Guenther Brunthaler

Thanks a lot, Tom and Attila!

tom_usenet said:
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.)
 
T

tom_usenet

Thanks a lot, Tom and Attila!



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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top