Defining Non-Member Functions for Template Member Types

Discussion in 'C++' started by flounder, Apr 1, 2009.

  1. flounder

    flounder Guest

    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
    }
     
    flounder, Apr 1, 2009
    #1
    1. Advertising

  2. * 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!

    --
    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!
     
    Alf P. Steinbach, Apr 1, 2009
    #2
    1. Advertising

  3. flounder

    James Kanze Guest

    On Apr 1, 3:52 am, "Alf P. Steinbach" <> wrote:
    > * 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.


    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.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Apr 1, 2009
    #3
  4. flounder wrote:

    > 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

    --
    Quidquid latine scriptum est, altum videtur.
     
    Martin Eisenberg, Apr 1, 2009
    #4
  5. flounder

    flounder Guest

    On Mar 31, 8:52 pm, "Alf P. Steinbach" <> wrote:
    > * 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!
    >
    > --
    > 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. ;-)
     
    flounder, Apr 2, 2009
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. claude uq
    Replies:
    3
    Views:
    539
    tom_usenet
    Dec 18, 2003
  2. johny smith
    Replies:
    8
    Views:
    450
    Peter Koch Larsen
    Jul 2, 2004
  3. Replies:
    2
    Views:
    502
    John Harrison
    Nov 9, 2005
  4. Hicham Mouline
    Replies:
    0
    Views:
    456
    Hicham Mouline
    Apr 23, 2009
  5. Hicham Mouline
    Replies:
    1
    Views:
    445
    Michael DOUBEZ
    Apr 24, 2009
Loading...

Share This Page