why is operator<< not found

H

homsan toft

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::eek:stream& operator<<(std::eek:stream& 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::eek:stream& operator<<(std::eek:stream& 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::eek:stream& operator<<(std::eek:stream& 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;
}
 
V

Victor Bazarov

homsan said:
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?


// (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()?

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)

???
template<class PartT>
inline std::eek:stream& operator<<(std::eek:stream& ostr, typename
Outer<PartT>::inner const& it) {
ostr << it.p.size << " by Jove\n";
return ostr;
}

// Nor is this found - what gives?

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?
 
H

homsan toft

Victor said:
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)

???

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.
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?

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
 
B

Bo Persson

homsan toft said:
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.

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

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.

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


Bo Persson
 
E

Earl Purple

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



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

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).
 

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,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top