Connecting Tech Pros Worldwide Forums | Help | Site Map

why is operator<< not found

homsan toft
Guest
 
Posts: n/a
#1: May 31 '06
I've tried the below code with MSVC and Comeau online compiler.
Both complain that operator<< for Outer<part<size_t> >::inner is not defined.
So how do I declare it without doing full specialization?

I've tried a template on any type, like Outer<AnyT>::inner (see below)
Also tried a template on the templated type: Outer<part<X> >::inner // (see below)
I can't find a typo? What is the rule in operation here?

Thanks,
homsan
---------------- 8< -----------------

#include <iostream>

template<class SizeT>
struct part {
typedef SizeT size_type;
size_type size;
};

template<class PartT>
class Outer
{
public:
typedef PartT part_type;
struct inner {
part_type p;
};
inner get() const { return inner(); }
};

// WHY is this not found in main()?
template<class PartT>
inline std::ostream& operator<<(std::ostream& ostr, typename Outer<PartT>::inner const& it)
{
ostr << it.p.size << " by Jove\n";
return ostr;
}

// Nor is this found - what gives?
template<class SizeT>
inline std::ostream& operator<<(std::ostream& ostr, typename Outer<part<SizeT> >::inner const& it)
{
ostr << it.p.size << " by Jove\n";
return ostr;
}

// Now this works, but of course I don't want to redefine for every specialization...
/*
std::ostream& operator<<(std::ostream& ostr, Outer<part<size_t> >::inner const& it)
{
ostr << it.p.size << " by Jove\n";
return ostr;
}
*/

int main() {
Outer<part<size_t> > yippie;
std::cout << yippie.get();
return 0;
}


Victor Bazarov
Guest
 
Posts: n/a
#2: May 31 '06

re: why is operator<< not found


homsan toft wrote:[color=blue]
> I've tried the below code with MSVC and Comeau online compiler.
> Both complain that operator<< for Outer<part<size_t> >::inner is not
> defined. So how do I declare it without doing full specialization?
>
> I've tried a template on any type, like Outer<AnyT>::inner (see
> below) Also tried a template on the templated type: Outer<part<X>[color=green]
> >::inner[/color]
> // (see below) I can't find a typo? What is the rule in operation here?
>
> Thanks,
> homsan
> ---------------- 8< -----------------
>
> #include <iostream>
>
> template<class SizeT>
> struct part {
> typedef SizeT size_type;
> size_type size;
> };
>
> template<class PartT>
> class Outer
> {
> public:
> typedef PartT part_type;
> struct inner {
> part_type p;
> };
> inner get() const { return inner(); }
> };
>
> // WHY is this not found in main()?[/color]

This is "non-deducible context". You're not using 'PartT' here.
Why do you think you need it? Why couldn't you use

template<class Blah> ..., Blah const& it)

???
[color=blue]
> template<class PartT>
> inline std::ostream& operator<<(std::ostream& ostr, typename
> Outer<PartT>::inner const& it) {
> ostr << it.p.size << " by Jove\n";
> return ostr;
> }
>
> // Nor is this found - what gives?[/color]

It's called "non-deducible context". Why do you need to know 'SizeT'
anyway?
You're not using it. Why could't you simply use OuterInner?
[color=blue]
> template<class SizeT>
> inline std::ostream& operator<<(std::ostream& ostr, typename
> Outer<part<SizeT> >::inner const& it) {
> ostr << it.p.size << " by Jove\n";
> return ostr;
> }
>
> // Now this works, but of course I don't want to redefine for every
> specialization... /*
> std::ostream& operator<<(std::ostream& ostr, Outer<part<size_t>[color=green]
> >::inner const& it) {[/color]
> ostr << it.p.size << " by Jove\n";
> return ostr;
> }
> */
>
> int main() {
> Outer<part<size_t> > yippie;
> std::cout << yippie.get();
> return 0;
> }[/color]



--
Please remove capital As from my address when replying by mail


homsan toft
Guest
 
Posts: n/a
#3: May 31 '06

re: why is operator<< not found


Victor Bazarov wrote:
[color=blue][color=green]
>>
>>template<class PartT>
>>class Outer
>>{
>>public:
>>typedef PartT part_type;
>>struct inner {
>>part_type p;
>>};
>>inner get() const { return inner(); }
>>};
>>
>>// WHY is this not found in main()?
>>template<class PartT>
>>inline std::ostream& operator<<(std::ostream& ostr, typename Outer<PartT>::inner const& it) {[/color]
>
> This is "non-deducible context". You're not using 'PartT' here.
> Why do you think you need it? Why couldn't you use
>
> template<class Blah> ..., Blah const& it)
>
> ???[/color]

Ah, so I can't specialize or overload on a nested type (the Standard forbids).
Thanks Victor, found out now by search on the phrase you provided.
[color=blue][color=green]
>>template<class SizeT>
>>inline std::ostream& operator<<(std::ostream& ostr, typename Outer<part<SizeT> >::inner const& it) {[/color]
>
> It's called "non-deducible context". Why do you need to know 'SizeT' anyway?
> You're not using it. Why could't you simply use OuterInner?[/color]

And so you mean a *non-nested type* OuterInner.
Ok, either that or define a method print(ostream&) on Outer<T>::inner,
and/or require specializing operator<< for every Outer<T> there may be.

Of course my real code uses several representations of part<SizeT> with 16/32/64-bit
size types, and both Outer and inner use the part_type all over.

I thought it nice to make the /part_type/ of struct inner explicitly dependent on its
Outer owner (Outer is a container of inner's), but as you say it brings other problems.
So will reconsider my (ahem) design.

Thanks,

homsan





Bo Persson
Guest
 
Posts: n/a
#4: May 31 '06

re: why is operator<< not found



"homsan toft" <nowhere@specific.org> skrev i meddelandet
news:e5k5nf$6sq$1@oden.abc.se...[color=blue]
> Victor Bazarov wrote:
>[color=green]
>> It's called "non-deducible context". Why do you need to know
>> 'SizeT' anyway?
>> You're not using it. Why could't you simply use OuterInner?[/color]
>
> And so you mean a *non-nested type* OuterInner.
> Ok, either that or define a method print(ostream&) on
> Outer<T>::inner,
> and/or require specializing operator<< for every Outer<T> there may
> be.[/color]

No, if you want to output the 'inner' type, you should specialize
operator<< for 'inner' !

Outer<T> has nothing to do with the operator, if it is 'inner' you
want it to operate on.
[color=blue]
>
> Of course my real code uses several representations of part<SizeT>
> with 16/32/64-bit
> size types, and both Outer and inner use the part_type all over.[/color]

And those size types already have operator<< defined for them, right?


Bo Persson


Earl Purple
Guest
 
Posts: n/a
#5: May 31 '06

re: why is operator<< not found



Bo Persson wrote:[color=blue]
> "homsan toft" <nowhere@specific.org> skrev i meddelandet
> news:e5k5nf$6sq$1@oden.abc.se...[color=green]
> > Victor Bazarov wrote:
> >[color=darkred]
> >> It's called "non-deducible context". Why do you need to know
> >> 'SizeT' anyway?
> >> You're not using it. Why could't you simply use OuterInner?[/color]
> >
> > And so you mean a *non-nested type* OuterInner.
> > Ok, either that or define a method print(ostream&) on
> > Outer<T>::inner,
> > and/or require specializing operator<< for every Outer<T> there may
> > be.[/color]
>
> No, if you want to output the 'inner' type, you should specialize
> operator<< for 'inner' !
>
> Outer<T> has nothing to do with the operator, if it is 'inner' you
> want it to operate on.
>[color=green]
> >
> > Of course my real code uses several representations of part<SizeT>
> > with 16/32/64-bit
> > size types, and both Outer and inner use the part_type all over.[/color]
>
> And those size types already have operator<< defined for them, right?[/color]

The "trick" workaround is to put it in its own namespace and make it
generic for that namespace. The outer class is specialised if that has
its own output. You can only do that for one nested class within an
outer class.

And if you're going to define a namespace anyway, just make the class
non-nested. You can then typedef it into your outer class if you want
to use it in templates. (ie outerClass<T>::inner would be typedef'ed).

Closed Thread