ambient swap template not found.

Discussion in 'C++' started by Kai-Uwe Bux, Oct 8, 2005.

  1. Kai-Uwe Bux

    Kai-Uwe Bux Guest

    Hi folks,


    I am still struggling with the rules for name lookup.


    Please consider:

    namespace xxx {

    struct empty {};

    void swap ( empty & a, empty & b ) {}

    template < typename T >
    struct stupid {

    T data;

    void swap ( stupid & other ) { // line 12
    swap( this->data, other.data ); // line 13
    }

    };

    }

    int main ( void ) {
    xxx::stupid< xxx::empty > a, b;
    a.swap(b); // line 22
    }


    The compiler complains:

    In member function 'void xxx::stupid<T>::swap(xxx::stupid<T>&)
    [with T = xxx::empty]':
    file.cc:22: instantiated from here
    file.cc:13: error: no matching function for call to
    'xxx::stupid<xxx::empty>:
    :swap(xxx::empty&, xxx::empty&)'
    file.cc:12: note: candidates are: void xxx::stupid<T>::swap(xxx::stupid<T>&)
    [with T = xxx::empty]


    Obviously, the presence of the local swap-method in stupid<T> prevents the
    compiler from looking outside for other possible swaps. I was under the
    impression that the namespace where T (in this case xxx::empty) is defined
    would be searched for a match. But that apparently does not happen. Why is
    that?


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Oct 8, 2005
    #1
    1. Advertising

  2. Kai-Uwe Bux wrote:
    > I am still struggling with the rules for name lookup.
    >
    >
    > Please consider:
    >
    > namespace xxx {
    >
    > struct empty {};
    >
    > void swap ( empty & a, empty & b ) {}
    >
    > template < typename T >
    > struct stupid {
    >
    > T data;
    >
    > void swap ( stupid & other ) { // line 12
    > swap( this->data, other.data ); // line 13
    > }
    >
    > };
    >
    > }
    >
    > int main ( void ) {
    > xxx::stupid< xxx::empty > a, b;
    > a.swap(b); // line 22
    > }
    >
    >
    > The compiler complains:
    >
    > In member function 'void xxx::stupid<T>::swap(xxx::stupid<T>&)
    > [with T = xxx::empty]':
    > file.cc:22: instantiated from here
    > file.cc:13: error: no matching function for call to
    > 'xxx::stupid<xxx::empty>:
    >> swap(xxx::empty&, xxx::empty&)'

    > file.cc:12: note: candidates are: void
    > xxx::stupid<T>::swap(xxx::stupid<T>&) [with T = xxx::empty]
    >
    >
    > Obviously, the presence of the local swap-method in stupid<T>
    > prevents the compiler from looking outside for other possible swaps.


    No, it does not prevent it from looking. It prevents the compiler
    from seeing it.

    > I was under the impression that the namespace where T (in this case
    > xxx::empty) is defined would be searched for a match. But that
    > apparently does not happen. Why is that?



    It's called "name hiding", I believe. 'swap' name in the struct
    'stupid' scope _hides_ the one in the namespace scope, so while
    you're in 'xxx::stupid::swap', the other one is simply invisible.

    V
    Victor Bazarov, Oct 8, 2005
    #2
    1. Advertising

  3. Kai-Uwe Bux

    Kai-Uwe Bux Guest

    Victor Bazarov wrote:

    > Kai-Uwe Bux wrote:
    >> I am still struggling with the rules for name lookup.
    >>
    >>
    >> Please consider:
    >>
    >> namespace xxx {
    >>
    >> struct empty {};
    >>
    >> void swap ( empty & a, empty & b ) {}
    >>
    >> template < typename T >
    >> struct stupid {
    >>
    >> T data;
    >>
    >> void swap ( stupid & other ) { // line 12
    >> swap( this->data, other.data ); // line 13
    >> }
    >>
    >> };
    >>
    >> }
    >>

    [snip]
    >
    >> I was under the impression that the namespace where T (in this case
    >> xxx::empty) is defined would be searched for a match. But that
    >> apparently does not happen. Why is that?

    >
    >
    > It's called "name hiding", I believe. 'swap' name in the struct
    > 'stupid' scope _hides_ the one in the namespace scope, so while
    > you're in 'xxx::stupid::swap', the other one is simply invisible.



    Thanks a lot for the explanation. However, that leaves me with a problem:
    how to tell the template stupid<T> which swap to use. I considered:

    template < typename T >
    struct stupid {

    T data;

    void swap ( stupid & other ) {
    std::swap( this->data, other.data );
    }

    };

    This, I think, will not find specialized/overloaded version of swap for
    types not declared in namespace std; and I cannot dump my stuff in there.

    Thus, I did:

    namespace xxx {

    struct empty {};

    void swap ( empty & a, empty & b ) {}

    template < typename T >
    void global_swap ( T & a, T & b ) {
    swap( a, b );
    }

    template < typename T >
    struct stupid {

    T data;

    void swap ( stupid & other ) {
    global_swap( this->data, other.data );
    }

    };

    }

    This will find the appropriate swap by looking at the argument type. But
    introducing the forwarding function "global_swap" seems clumsy. I would
    appreciate suggestions for how to improve upon this.


    Thanks again

    Kai-Uwe Bux
    Kai-Uwe Bux, Oct 8, 2005
    #3
  4. Kai-Uwe Bux wrote:
    > [..]
    > Thanks a lot for the explanation. However, that leaves me with a
    > problem: how to tell the template stupid<T> which swap to use. I
    > considered:
    >
    > template < typename T >
    > struct stupid {
    >
    > T data;
    >
    > void swap ( stupid & other ) {
    > std::swap( this->data, other.data );
    > }
    >
    > };
    >
    > This, I think, will not find specialized/overloaded version of swap
    > for types not declared in namespace std; and I cannot dump my stuff
    > in there.


    Yes, you can.

    "17.4.3.1 Reserved names
    [...]. A program may add template specializations for any
    standard library template to namespace std. [...]"

    So, you're totally allowed to specialise 'swap' for your class 'empty'
    and put it in 'std' namespace.

    > [...]


    V
    Victor Bazarov, Oct 9, 2005
    #4
  5. "Kai-Uwe Bux" <> wrote in message
    news:di937k$7i1$...
    > Hi folks,
    >
    >
    > I am still struggling with the rules for name lookup.
    >
    >
    > Please consider:
    >
    > namespace xxx {
    >
    > struct empty {};
    >
    > void swap ( empty & a, empty & b ) {}
    >
    > template < typename T >
    > struct stupid {
    >
    > T data;
    >
    > void swap ( stupid & other ) { // line 12
    > swap( this->data, other.data ); // line 13
    > }
    >


    how bout xxx::swap instead?

    Jon
    Jon Slaughter, Oct 9, 2005
    #5
  6. Jon Slaughter wrote:
    > "Kai-Uwe Bux" <> wrote in message
    > news:di937k$7i1$...
    >> Hi folks,
    >>
    >>
    >> I am still struggling with the rules for name lookup.
    >>
    >>
    >> Please consider:
    >>
    >> namespace xxx {
    >>
    >> struct empty {};
    >>
    >> void swap ( empty & a, empty & b ) {}
    >>
    >> template < typename T >
    >> struct stupid {
    >>
    >> T data;
    >>
    >> void swap ( stupid & other ) { // line 12
    >> swap( this->data, other.data ); // line 13
    >> }
    >>

    >
    > how bout xxx::swap instead?


    That would not allow using 'std::swap' for T other than 'empty'.

    V
    Victor Bazarov, Oct 9, 2005
    #6
  7. "Victor Bazarov" <> wrote in message
    news:...
    > Jon Slaughter wrote:
    >> "Kai-Uwe Bux" <> wrote in message
    >> news:di937k$7i1$...
    >>> Hi folks,
    >>>
    >>>
    >>> I am still struggling with the rules for name lookup.
    >>>
    >>>
    >>> Please consider:
    >>>
    >>> namespace xxx {
    >>>
    >>> struct empty {};
    >>>
    >>> void swap ( empty & a, empty & b ) {}
    >>>
    >>> template < typename T >
    >>> struct stupid {
    >>>
    >>> T data;
    >>>
    >>> void swap ( stupid & other ) { // line 12
    >>> swap( this->data, other.data ); // line 13
    >>> }
    >>>

    >>
    >> how bout xxx::swap instead?

    >
    > That would not allow using 'std::swap' for T other than 'empty'.
    >
    > V


    Then he needs to specialize stupid::swap if T is of empty type to use
    xxx::swap?

    basicaly

    if T is of type empty then use xxx::swap else use std::swap

    or whatever
    Jon Slaughter, Oct 9, 2005
    #7
  8. Kai-Uwe Bux

    Kai-Uwe Bux Guest

    Victor Bazarov wrote:

    > Kai-Uwe Bux wrote:
    >> [..]
    >> Thanks a lot for the explanation. However, that leaves me with a
    >> problem: how to tell the template stupid<T> which swap to use. I
    >> considered:
    >>
    >> template < typename T >
    >> struct stupid {
    >>
    >> T data;
    >>
    >> void swap ( stupid & other ) {
    >> std::swap( this->data, other.data );
    >> }
    >>
    >> };
    >>
    >> This, I think, will not find specialized/overloaded version of swap
    >> for types not declared in namespace std; and I cannot dump my stuff
    >> in there.

    >
    > Yes, you can.
    >
    > "17.4.3.1 Reserved names
    > [...]. A program may add template specializations for any
    > standard library template to namespace std. [...]"
    >
    > So, you're totally allowed to specialise 'swap' for your class 'empty'
    > and put it in 'std' namespace.


    Great! Thanks for that crucial piece of information.


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Oct 9, 2005
    #8
    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. William Parker
    Replies:
    1
    Views:
    3,067
    Martin
    Jun 27, 2004
  2. Replies:
    3
    Views:
    530
  3. Niels Dekker (no reply address)

    What swap is called when using std::swap?

    Niels Dekker (no reply address), Jul 19, 2006, in forum: C++
    Replies:
    4
    Views:
    972
    Niels Dekker (no reply address)
    Jul 20, 2006
  4. panzhiyong
    Replies:
    3
    Views:
    576
    James Kanze
    Nov 27, 2007
  5. Bil Kleb
    Replies:
    5
    Views:
    190
    Mike Clark
    Aug 27, 2004
Loading...

Share This Page