I was implementing (for training purpose) a Bubble Sort template function:
template<typename iterInput,
typename predicate>
void BubbleSort(iterInput first1,iterInput last1,predicate func)
{
bool swapped(false);
do
{
swapped = false;
iterInput begin = first1;
iterInput beginMinus = first1;
++begin;
for (;begin != last1; begin++,beginMinus++)
{
if (func(*beginMinus,*begin) )
{
std::swap(*beginMinus,*begin);
swapped = true;
}
}
}
while(swapped);
}
When I have realized that this function will not work for class with no assignment operator, like this one (forgive me for the bad name):
class NoCopyable
{
public:
explicit NoCopyable(int value) : value_(value) {}
NoCopyable(const NoCopyable& other) : value_(other.value_) {}
~NoCopyable() {}
bool operator<(const NoCopyable& other) { return value_ < other.value_; }
void setValue(int value) { value_ = value; }
std::ostream& print(std::ostream& os) const { return os << value_; }
private:
NoCopyable& operator=(const NoCopyable& other);
int value_;
};
std::ostream& operator<<(std::ostream& os, const NoCopyable& obj)
{
return obj.print(os);
}
struct PrintNoCopyable
{
void operator()(const NoCopyable& noCopyable) { std::cout << noCopyable << '\n'; }
};
The compiler raises this error Error 1 error C2248: ‘NoCopyable::operator =’ : cannot access private member declared in class ‘NoCopyable’
So, I have slightly modify the code using instead of the std::swap function my version of the swap function, here is the code:
template<typename T1,
typename T2>
void noAssignmentSwap(T1& t1,T2& t2)
{
T1 temp(t1);
t1.~T1();
new (&t1) T1(t2);
t2.~T2();
new (&t2) T2(temp);
}
The code compiles and gives the right result. However I am not completely sure, I remember a Sutter’s article that suggest you to avoid playing with the objects life time. The article just warns you by playing with fire without actually giving you any real reason. I can see problem in exception safety if the copy constructor of T1 or T2 can throw. However there is the same problem in the standard version if the assignment operator is allowed to throw.
Here the question, can you see any possible drawbacks in this version of swap?
Cheers
The difference is that when the assignment operator fails, you still have the same number of objects.
If you destroy one object and fail to create a new one, one object is lost! If it was part of a container, the container’s state is probably also invalid.