How to overload std::swap()

A couple of additions to Mike Stone's reply:

std::swap() is used by many std containers (such as std::list and std::vector) during sorting and even assignment.

1) The most frequent thing I use TestNG's groups for is when I want to run a single test method in a test suite. I simply add this test to the group "phil" and then run this group. When I was using JUnit 3, I would comment out the entries for all methods but the one I wanted to run in the "suite" method, but then would commonly forget to uncomment them before checkin. With the groups, I no longer have this problem.

But the std implementation of swap() is very generalized and rather inefficient for custom types.

2) Depending on the complexity of the tests, migrating tests from JUnit3 to TestNG can be done somewhat automatically with sed and creating a base class to replace TestCase that static imports all of the TestNG assert methods.

Thus efficiency can be gained by overloading std::swap() with a custom type specific implementation. But how can you implement it so it will be used by the std containers?

36288 次浏览

You're not allowed (by the C++ standard) to overload std::swap, however you are specifically allowed to add template specializations for your own types to the std namespace. E.g.

namespace std
{
template<>
void swap(my_type& lhs, my_type& rhs)
{
// ... blah
}
}

then the usages in the std containers (and anywhere else) will pick your specialization instead of the general one.

Also note that providing a base class implementation of swap isn't good enough for your derived types. E.g. if you have

class Base
{
// ... stuff ...
}
class Derived : public Base
{
// ... stuff ...
}


namespace std
{
template<>
void swap(Base& lha, Base& rhs)
{
// ...
}
}

I have info on my migration from JUnit to TestNG here and here.

this will work for Base classes, but if you try to swap two Derived objects it will use the generic version from std because the templated swap is an exact match (and it avoids the problem of only swapping the 'base' parts of your derived objects).

t match (and it avoids the problem of only swapping the 'base' parts of your derived objects).

NOTE: I've updated this to remove the wrong bits from my last answer. D'oh! (thanks puetzk and j_random_hacker for pointing it out)

Your question seems two folded to me. On one had you would like to compare two test frameworks, on the other hand you would like to implement tests easily, have natural assertions, etc...

There is a thread on comp.lang.c++.moderated with a long dicussion of the topic. Most of it is about partial specialization, though (which there's currently no good way to do).

Ok, firstly JUnit has been playing catchup with TestNG in terms of functionality, they have bridged the gap some what with v4, but not well enough in my opinion. Things like annotations and dataproviders are still much better in TestNG. Also they are more flexible in terms of test execution, since TestNG has test dependency, grouping and ordering.

est. Make use of javas inheritance/interfaces to reduce repetition and enforce commonality.

JUnit still requires certain before/after methods to be static, which limits what you can do prior to the running of tests, TestNG never has this issue.

TBH, mostly the differences between the two frameworks don't mean much, unless your focusing on integration/automation testing. JUnit from my experience is built from the ground up for unit testing and is now being pushed towards higher levels of testing, which IMO makes it the wrong tool for the job. TestNG does well at unit testing and due to its robust dataproviding and great test execution abilities, works even better at integration/automation test level.

Almost forgot, also use the Test Data Builder Pattern, this coupled with TestNG's dataprovider annotation is very useful.

The right way to overload std::swap's implemention (aka specializing it), is to write it in the same namespace as what you're swapping, so that it can be found via argument-dependent lookup (ADL). One particularly easy thing to do is:

class X
{
// ...
friend void swap(X& a, X& b)
{
using std::swap; // bring in swap for built-in types


swap(a.base1, b.base1);
swap(a.base2, b.base2);
// ...
swap(a.member1, b.member1);
swap(a.member2, b.member2);
// ...
}
};

works! So why not use that?

JUnit 4 Vs TestNG – Comparison by mkyong.com ( updated on 2013).

Consider the case that your A is a class template:

// simulate user code which includes <algorithm>


template <class T>
struct A
{
};


namespace exp
{


template <class T>
void swap(A<T>&, A<T>&)
{
printf("exp::swap(A, A)\n");
}


}


// exercise simulation


int main()
{
A<int> a[2];
exp::algorithm(a, a+2);
}

Now it doesn't work again. :-(

Conclusion: I suggest to use TestNG as core unit test framework for Java project, because TestNG is more advance in parameterize testing, dependency testing and suite testing (Grouping concept).

So you could put swap in namespace std and have it work. But you'll need to remember to put swap in A's namespace for the case when you have a template: A<T>. And since both cases will work if you put swap in A's namespace, it is just easier to remember (and to teach others) to just do it that one way.