Defining Non-Member Functions for Template Member Types

F

flounder

The compiler is unable to find a match for the call to munge() and
operator==() in is_equal() below. Can someone post an explanation and/
or suggest a workaround?

Thanks!

template<class T>
struct Foo {
struct Bar {};
};

template<class T>
bool operator==(const typename Foo<T>::Bar&, const typename
Foo<T>::Bar&);

template<class T>
void munge(typename Foo<T>::Bar* );

inline bool
is_equal(Foo<int>::Bar x, Foo<int>::Bar y)
{
munge(&x);
return x == y; // no operator "==" matches these operands
}
 
A

Alf P. Steinbach

* flounder:
The compiler is unable to find a match for the call to munge() and
operator==() in is_equal() below. Can someone post an explanation and/
or suggest a workaround?

Thanks!

template<class T>
struct Foo {
struct Bar {};
};

template<class T>
bool operator==(const typename Foo<T>::Bar&, const typename
Foo<T>::Bar&);

template<class T>
void munge(typename Foo<T>::Bar* );

inline bool
is_equal(Foo<int>::Bar x, Foo<int>::Bar y)
{
munge(&x);
return x == y; // no operator "==" matches these operands
}

I googled.

See <url: http://www.codeguru.com/forum/archive/index.php/t-395268.html>;
"non-deduced context".

However while it seems the facts there are OK, the rationalization there seems
very fishy to me. Perhaps that rationalization is the standard's rationale (I'm
too lazy to check). But in a context like above I see no good reason why the
language could not have permitted the matching: there can be only one match.

I can see a bad reason, though, namely treating all types the same way, and the
above would indeed be problematic with Bar a typedef'ed name, e.g. for 'int'.

But the reason we use types and scopes (argh, declarative regions[1], now that
the C++ standardization has redefined our terminology) and so on is exactly to
discriminate between different things, even things that are technically the same
but just conceptually different, and I think the language should support that.

If the language had supported it then I think one would have had to write e.g.

template< typename T >
void munge( struct Foo<T>::Bar* );

But since the language doesn't support it the issue is moot.

Cheers & hth.,

- Alf


Notes:
[1] Or whatever the proper C++ term is!
 
J

James Kanze

* flounder:
I googled.
However while it seems the facts there are OK, the
rationalization there seems very fishy to me. Perhaps that
rationalization is the standard's rationale (I'm too lazy to
check). But in a context like above I see no good reason why
the language could not have permitted the matching: there can
be only one match.

The problem is that in the general case, at least, the compiler
would have to verify all of the possible expansions of Foo<>.
Suppose, for example, one of them expanded to contain:
typedef typename Foo<int>::Bar Bar ;
.. (That would make the call ambiguous.) It's easy for a human,
looking at the template definition, and knowing that there are
no explicit specializations, to realize that this could not be
the case, but this realization is based on a higher degree of
logic than compilers are capable of.
I can see a bad reason, though, namely treating all types the
same way, and the above would indeed be problematic with Bar a
typedef'ed name, e.g. for 'int'.

Exactly. And you don't know what Bar will be in Foo<T> until
you've instantiated Foo<T>.

The problem is that we humans (most of us, anyway) can think
very well in abstract terms, along the lines of "for all T...".
Machines can't, or at least, current compilers don't incorporate
any technology that can.
 
M

Martin Eisenberg

flounder said:
The compiler is unable to find a match for the call to munge()
and operator==() in is_equal() below. Can someone post an
explanation and/ or suggest a workaround?

Regarding operators, you might (ab)use definitions in friend
declarations:

template<class T>
struct Foo {
struct Bar {
friend bool operator==(const Bar&, const Bar&)
{ return true; }
};
};

This puts one non-template free operator==() per Foo<T> instance in
Foo's enclosing namespace. Regarding functions that aren't known at
the time of declaration of Bar or shouldn't always be declared along
with it, I suppose the next best thing is to make them fully generic
and then constrain with Boost's Concept Check or enable_if. However,
enable_if still won't let you derive type T (or Foo<T>) in such a
function.


Martin
 
F

flounder

* flounder:




The compiler is unable to find a match for the call to munge() and
operator==() in is_equal() below.  Can someone post an explanation and/
or suggest a workaround?

template<class T>
struct Foo {
    struct Bar {};
};
template<class T>
bool operator==(const typename Foo<T>::Bar&,  const typename
Foo<T>::Bar&);
template<class T>
void munge(typename Foo<T>::Bar* );
inline bool
is_equal(Foo<int>::Bar x, Foo<int>::Bar y)
{
    munge(&x);
    return x == y;    // no operator "==" matches these operands
}

I googled.

See <url:http://www.codeguru.com/forum/archive/index.php/t-395268.html>;
"non-deduced context".

However while it seems the facts there are OK, the rationalization there seems
very fishy to me. Perhaps that rationalization is the standard's rationale (I'm
too lazy to check). But in a context like above I see no good reason why the
language could not have permitted the matching: there can be only one match.

I can see a bad reason, though, namely treating all types the same way, and the
above would indeed be problematic with Bar a typedef'ed name, e.g. for 'int'.

But the reason we use types and scopes (argh, declarative regions[1], now that
the C++ standardization has redefined our terminology) and so on is exactly to
discriminate between different things, even things that are technically the same
but just conceptually different, and I think the language should support that.

If the language had supported it then I think one would have had to write e.g.

   template< typename T >
   void munge( struct Foo<T>::Bar* );

But since the language doesn't support it the issue is moot.

Cheers & hth.,

- Alf

Notes:
[1] Or whatever the proper C++ term is!

--
Due to hosting requirements I need visits to <url:http://alfps.izfree.com/>.
No ads, and there is some C++ stuff! :) Just going there is good. Linking
to it is even better! Thanks in advance!- Hide quoted text -

- Show quoted text -

Thanks to all for your replies. Alf, you're clearly a better Google'r
than I. ;-)
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top