Re: specializing swap for nested iterator class
Am 21.04.2012 09:51, schrieb galexander2@nc.rr.com:
I'm developing my own container class and have implemented the
container's iterator as a nested class. I want to include a
specialized version of swap for the iterator. Here's a small
example of what I tried:
#include<cstdlib>
#include<functional>
#include<iostream>
#include<memory>
#include<utility>
namespace ns {
template<class Key, class Compare = std::less<Key>, class
Allocator = std::allocator<Key> >
class myContainer {
public:
class iterator_implementation {
public:
inline iterator_implementation() {
}
};
public:
typedef iterator_implementation iterator;
};
template<class Key, class Compare, class Allocator>
inline void swap(typename myContainer<Key, Compare,
Allocator>::iterator& x,
typename myContainer<Key, Compare,
Allocator>::iterator& y) {
std::cout<< "**** specialized iterator swap ****"<< std::endl;
}
}
The problem is located here in the signature of your function
template: A parameter like
typename myContainer<Key, Compare,Allocator>::iterator
is always very suspicious unless designed carefully: It does not allow
by-argument deduction of the template parameters. I did not check the
FAQ, but this should actually belong to the FAQ list: A
type-construction like
typename /some_template/</some_arguments/>::/some_type/
where some_arguments needs to be deduced is always an undeduced
context, because in general the compiler cannot find the set of
some_arguments given a dependent type some_type: This is like finding
an inverse function: To find the inverse of a mathematical function
requires that this function is invertible (i.e. there are some
constraints imposed), which is a unique inverse relation. C++
templates are not (in general) invertible type/value functions.
int main(int argc, char* argv[]) {
ns::myContainer<int>::iterator x =
ns::myContainer<int>::iterator();
ns::myContainer<int>::iterator y =
ns::myContainer<int>::iterator();
using std::swap;
std::cout<< "before swap(x, y)"<< std::endl;
swap(x, y);
std::cout<< "after swap(x, y)"<< std::endl;
std::cout<< std::endl;
std::cout<< "before swap<int, std::less<int>, std::allocator<int>
(x, y)"<< std::endl;
swap<int, std::less<int>, std::allocator<int> >(x, y);
std::cout<< "after swap<int, std::less<int>, std::allocator<int>
(x, y)"<< std::endl;
exit(0);
}
The problem is that swap(x, y) calls std::swap rather than the
specialized ns:swap. It seems that ADL isn't finding ns:swap. To
call ns:swap, one has to specify template arguments as in for
example swap<int, std::less<int>, std::allocator<int> >(x, y), which
isn't what I want. Is this correct behavior according to the C++
standard?
Yes, that is to be expected: You swap overload can never be called by
argument deduction.
Or is it a compiler bug? If this is correct standard behavior, can
someone point to where this behavior is described?
This is described in 14.8.2.5 [temp.deduct.type] p4-6, in particular
see p5:
"The non-deduced contexts are:
? The nested-name-specifier of a type that was specified using a
qualified-id."
combined with p6:
"When a type name is specified in a way that includes a non-deduced
context, all of the types that comprise that type name are also
non-deduced."
In your example "myContainer<Key, Compare, Allocator>" is the above
mentioned nested-name-specifier and the referred to type is
"myContainer<Key, Compare, Allocator>::iterator".
In this case is there a standard way to define a specialize swap for
iterator short of making the iterator_implementation class its own
stand-alone class rather than a nested class?
The most simple one is to add a defining in-class friend function to
your iterator type such as:
namespace ns {
template<class Key, class Compare = std::less<Key>, class
Allocator = std::allocator<Key> >
class myContainer {
public:
class iterator_implementation {
public:
inline iterator_implementation() {
}
friend void swap(iterator_implementation& x,
iterator_implementation& y) {
std::cout << "**** specialized iterator swap ****" <<
std::endl;
}
};
public:
typedef iterator_implementation iterator;
};
}
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]