stream operator of a class nested in a class template

A

Ares Lagae

How is an output stream operator of a class nested in a class template
defined? The code fragment below does not compile. Maybe it's just me,
but I don't see why it should not compile.

Best regards,

#include <iostream>

template <typename T>
struct foo
{
struct bar {};
bar bar_;
const bar& get_bar() const { return bar_; }
};

template <typename Ch, typename Tr, typename T>
std::basic_ostream<Ch,Tr>& operator<<(std::basic_ostream<Ch,Tr>&
ostream, typename foo<T>::bar&)
{
return ostream;
}

int main()
{
foo<int> f;
const foo<int>::bar& b = f.get_bar();
std::cout << b << "\n";
}

Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for
ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 21: error: no operator "<<" matches these
operands
operand types are: std::eek:stream << const foo<int>::bar
std::cout << b << "\n";
^

1 error detected in the compilation of "ComeauTest.c".
 
A

Ares Lagae

Thank you for your quick reply.
Your argument is declared non-const here, but you pass a const ref.

I have added "const" but that did not change anything.
Also, this is a non-deducible context.

So it seems. The call "operator<< <char, std::char_traits<char>,
int>(std::cout, b)" works.

Can you explain Why?

Best regards,

Ares
 
J

James Kanze

Explain why what?  Why it's a non-deducible context?  I don't
know. Here, the boilerplate answer is "because the Standard
says so", but why it's so in the Standard...  There are
*probably* cases in which the compiler would have hard time
deciding and the Standard Committee did not want to impose the
"undue hardship" on the compiler implementors. But your guess
is probably as good as mine.  Try looking in the archives for
"non-deducible context".

I wasn't present during the discussions concerning this
particular point, but I can make some good guesses as to why it
isn't deducible. In the general case, the only way to deduce it
would be to try every possible instantiation, to see if one
matches---until you've instantiated Outer<T>, you can't know
what Outer<T>::Inner is. Given that the number of possible
instantiations is infinite, the committee probably felt that
this was asking a little too much of the implementors.
 

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

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top