Argument Dependent Lookup and stream operators overloading - c++

I have a library which expose some sort of container struct in which I want to collect diverse generic type of data which might be from the same namespace of the library as well as data from the std namespace such as array or tuple or pairs.
This container has a print_all method which will invoke operator<< for all the elements in the container. Such an operator is supposed to be provided by the user of the library.
Testing the library, I am using different template parameters for T, but I do not care too much about what is being printed by the print_all method. For the test purpose I care only that an example character is being printed no matter which T is being tested. Actually, I my real code I am using Google Test Framework and the behavior of the method under test is really asserted to be the same for every data type provided.
I tried to provide both a generic version of operator<< and two specific versions of it. You can see them in between the #if directive. None of the two compilation branches compiles correctly, most likely because of some violation of the König lookup rules. But anyway what I want to do should be easily possible somehow. What am I missing?
Here is the example code:
#include <algorithm>
#include <iostream>
#include <vector>
namespace my
{
template<typename DataType>
struct Container
{
void print_all( std::ostream& os ) const
{
std::for_each(std::begin(data),
std::end(data),
[&os](const DataType& value)
{
os << value;
});
}
std::vector<DataType> data;
};
namespace test
{
struct Data
{
std::byte data[4];
};
using Array = std::array<std::byte,4>;
#if 0
template<typename T>
std::ostream& operator<<(std::ostream& os, const T& data)
{
return os << 'X';
}
#else
std::ostream& operator<<(std::ostream& os, const Data& data)
{
return os << 'X';
}
std::ostream& operator<<(std::ostream& os, const Array& data)
{
return os << 'X';
}
#endif
void run()
{
// Test with custom data
{
Container< Data> container;
container.data.resize(1);
container.print_all( std::cout );
}
// Test with std data
{
Container< Array> container;
container.data.resize(1);
container.print_all( std::cout );
}
}
} // namespace test
} // namespace my
int main()
{
my::test::run();
return 0;
}

ADL looks into the namespaces associates with the arguments.
using Array = std::array<std::byte,4>;
this type test::Array is an alias. The namespaces associated with it for the purpose of ADL is std. test is not associated with it. ADL will only look in std. You are not permitted to add operators to std; if you violate that, your program is ill-formed, no diagnostic required. ADL cannot help you, because it only helps people who own the namespace(s) associated with the arguments.
Any << you want to support in std needs to be in namespace my, defined before your print_all function.
Your code for Data looks to me like it works, I assume your question was just poorly written, as it implies os <<Data does not work. If I am wromg amd it doesn't work, it is because of some typo; ADL works fine on structs, but not on aliases. In the future, please include complete error messages when code doesn't work.

Related

how to overload std::ceil() in my program [duplicate]

std::swap() is used by many std containers (such as std::list and std::vector) during sorting and even assignment.
But the std implementation of swap() is very generalized and rather inefficient for custom types.
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?
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);
// ...
}
};
Attention Mozza314
Here is a simulation of the effects of a generic std::algorithm calling std::swap, and having the user provide their swap in namespace std. As this is an experiment, this simulation uses namespace exp instead of namespace std.
// simulate <algorithm>
#include <cstdio>
namespace exp
{
template <class T>
void
swap(T& x, T& y)
{
printf("generic exp::swap\n");
T tmp = x;
x = y;
y = tmp;
}
template <class T>
void algorithm(T* begin, T* end)
{
if (end-begin >= 2)
exp::swap(begin[0], begin[1]);
}
}
// simulate user code which includes <algorithm>
struct A
{
};
namespace exp
{
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
// exercise simulation
int main()
{
A a[2];
exp::algorithm(a, a+2);
}
For me this prints out:
generic exp::swap
If your compiler prints out something different then it is not correctly implementing "two-phase lookup" for templates.
If your compiler is conforming (to any of C++98/03/11), then it will give the same output I show. And in that case exactly what you fear will happen, does happen. And putting your swap into namespace std (exp) did not stop it from happening.
Dave and I are both committee members and have been working this area of the standard for a decade (and not always in agreement with each other). But this issue has been settled for a long time, and we both agree on how it has been settled. Disregard Dave's expert opinion/answer in this area at your own peril.
This issue came to light after C++98 was published. Starting about 2001 Dave and I began to work this area. And this is the modern solution:
// simulate <algorithm>
#include <cstdio>
namespace exp
{
template <class T>
void
swap(T& x, T& y)
{
printf("generic exp::swap\n");
T tmp = x;
x = y;
y = tmp;
}
template <class T>
void algorithm(T* begin, T* end)
{
if (end-begin >= 2)
swap(begin[0], begin[1]);
}
}
// simulate user code which includes <algorithm>
struct A
{
};
void swap(A&, A&)
{
printf("swap(A, A)\n");
}
// exercise simulation
int main()
{
A a[2];
exp::algorithm(a, a+2);
}
Output is:
swap(A, A)
Update
An observation has been made that:
namespace exp
{
template <>
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
works! So why not use that?
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. :-(
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.
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)
{
// ...
}
}
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).
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)
While it's correct that one shouldn't generally add stuff to the std:: namespace, adding template specializations for user-defined types is specifically allowed. Overloading the functions is not. This is a subtle difference :-)
17.4.3.1/1
It is undefined for a C++ program to add declarations or definitions
to namespace std or namespaces with namespace std unless otherwise
specified. A program may add template specializations for any
standard library template to namespace std. Such a specialization
(complete or partial) of a standard library results in undefined
behaviour unless the declaration depends on a user-defined name of
external linkage and unless the template specialization meets the
standard library requirements for the original template.
A specialization of std::swap would look like:
namespace std
{
template<>
void swap(myspace::mytype& a, myspace::mytype& b) { ... }
}
Without the template<> bit it would be an overload, which is undefined, rather than a specialization, which is permitted. #Wilka's suggest approach of changing the default namespace may work with user code (due to Koenig lookup preferring the namespace-less version) but it's not guaranteed to, and in fact isn't really supposed to (the STL implementation ought to use the fully-qualified std::swap).
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).

Simple types with higher meaning (C++11)

I often run into situations (in my C++/C++11 code), where I have a type that basically behaves like a built-in type (or a "basic simple" type like std::string), but that has a meaning
beyond a 32 bit number or a bunch of characters.
I didn't find anything useful on the Internet, because I don't really what terms to search for...
Examples:
I once worked on a system, where items were identified by an ID. And these IDs were std::strings (probably not the best idea in the first place, but that's a different story). What was really bad though was the fact, that these IDs were passed through the system as std::strings or as const char*s. So it was hard (impossible) to tell where in the
code base IDs were used when searching for the type. The variable names were all variations of ID(ID, id, Id) or key or just i or name or whatever. So you could not search by name either. So I'd prefer to pass those variables as type id_t.
Network ports: They are uint16_ts. But I would like to pass them as network_port_ts.
I generally used typedefs to make things a little nicer. This approach has multiple problems though:
You don't have to use the typedef. You can still pass variables around by the "raw" type (e.g. std::string instead of id_t).
If the raw type is a template, you are done with forward declaring the typedef (e.g. with a shared_ptr).
"Forward declaring" the typedef is a maintenance problem. If the raw type changes, you get to change stuff all over the place.
Another thing I tried with the network port example was writing a thin wrapper class sporting a operator uint16_t. This solved the problem with forward declarations. But then I ran
into a trap with some logging macros which used printf internally. The printfs still worked (well, compiled), but didn't print the port number, but (I think) the address of the object.
I figured with dimensions like weights or lengths Boost.Units might be worth a look (even so it appears a little "heavy"). But for the two examples above, it doesn't fit.
What is the best practice to achieve what I want (using Boost is an option)?
In short:
What I want to achieve is to pass "types with higher meaning" as its own type and not as the plain raw/low level/non-abstract type. (Kind of) like having a user defined type. Preferably without the huge overhead of writing a complete class for every type with basically identical implementations, only to be able to do what built-ins already can do.
1. Strong Typedefs
You can use BOOST_STRONG_TYPEDEF to get some convenience.
It does employ macros, and I think you get to do heterogeneous comparisons (e.g. id == "123").
There's two versions, be sure to take the one from Boost Utility.
2. flavoured_string<>
For strings you can cheat the system by using flavoured strings (inventor: R.Martinho Fernandes).
This leverages the fact that you can actually vary the traits on a std::basic_string, and create actually different tagged aliases:
#include <string>
#include <iostream>
namespace dessert {
template <typename Tag>
struct not_quite_the_same_traits : std::char_traits<char> {};
template <typename Tag>
using strong_string_alias = std::basic_string<char, not_quite_the_same_traits<Tag>>;
using vanilla_string = std::string;
using strawberry_string = strong_string_alias<struct strawberry>;
using caramel_string = strong_string_alias<struct caramel>;
using chocolate_string = strong_string_alias<struct chocolate>;
template <typename T>
struct special;
template <typename T>
using special_string = strong_string_alias<special<T>>;
std::ostream& operator<<(std::ostream& os, vanilla_string const& s) {
return os << "vanilla: " << s.data();
}
std::ostream& operator<<(std::ostream& os, strawberry_string const& s) {
return os << "strawberry: " << s.data();
}
std::ostream& operator<<(std::ostream& os, caramel_string const& s) {
return os << "caramel: " << s.data();
}
std::ostream& operator<<(std::ostream& os, chocolate_string const& s) {
return os << "chocolate: " << s.data();
}
template <typename T>
std::ostream& operator<<(std::ostream& os, special_string<T> const& s) {
return os << "special: " << s.data();
}
}
int main() {
dessert::vanilla_string vanilla = "foo";
dessert::strawberry_string strawberry = "foo";
dessert::caramel_string caramel = "foo";
dessert::chocolate_string chocolate = "foo";
std::cout << vanilla << '\n';
std::cout << strawberry << '\n';
std::cout << caramel << '\n';
std::cout << chocolate << '\n';
dessert::special_string<struct nuts> nuts = "foo";
std::cout << nuts << '\n';
}
To create an integer that's not an integer (or a string that's not a string) and cannot promote or demote to it), you can only create a new type, that merely means "write a new class". There is no way -at least on basic type- to inherit behaviour without aliasing. A new_type<int> has no arithmetic (unless you'll define it).
But you can define a
template<class Innertype, class Tag>
class new_type
{
Innertype m;
public:
template<class... A>
explicit new_type(A&&... a) :m(std::forward<A>(a)...) {}
const Innertype& as_native() const { return m; }
};
and do all the workout only once for all.
template<class T, class I>
auto make_new_type(I&& i)
{ return new_type<I,T>(std::forward<I>(i)); }
template<class A, class B, class T>
auto operator+(const new_type<A,T>& a, const new_type<B,T>& b)
{ return make_new_type<T>(a.as_native()+b.as_native()); }
....
and then
struct ID_tag;
typedef new_type<std::string,ID_tag> ID;
struct OtehrID_tag;
typedef new_type<std::string,OtehrID_tag> OtherID;
and ID oand OtherID cannot mix in expressions.
NOTE:
auto -function with unspecifyed return are standard from C++14, but GCC accepts it in C++11 as-well.
template <typename tag_t, typename value_t>
struct meaningful_value
{
typedef value_t value_type;
meaningful_value() : value() {}
explicit meaningful_value(const value_type & val) : value(val) {}
operator const value_type & () const { return value; }
protected:
value_type value;
};
typedef meaningful_value<struct ParamType1_tag, double> ParamType1;
typedef meaningful_value<struct ParamType2_tag, double> ParamType2;
This is basically what boost::quantity does, but allows for default construction; the tag struct can be declared inplace in the typedef, so declaring a new type of parameter is a single-line deal; you get to choose if you want a macro for it
(Edited to fix constructor name)

how to refactor this class template to minimize boiler-plate code?

I've recently started using boost mirror for ORM reflection so I can minimize the amount of DB-related boiler-plate code.
One kind of pattern I've run into is listed below.
Since Bar's code is going to look identical even for Baz, I was wondering, is it possible to collapse this code any further?
It would be nice if the getValues() interface would look the same, but the identical implementation could also live in Foo instead.
#include <iostream>
template< typename T >
struct Foo
{
static std::ostream& GetValues_Worker( std::ostream& os, T const& t )
{
// do boost mirror reflection stuff here
return os;
}
};
struct Bar :
public Foo<Bar>
{
// REFACTOR IF POSSIBLE: this code will always look the same - even for Baz
std::ostream&
getValues( std::ostream& os ) const
{
return GetValues_Worker( os, *this );
}
};
struct Baz :
public Foo<Baz>
{
// REFACTOR IF POSSIBLE: looks the same as Bar
std::ostream&
getValues( std::ostream& os ) const
{
return GetValues_Worker( os, *this );
}
};
int main( int argc, char* argv[] )
{
Bar b;
std::cerr << b.getValues( std::cerr ) << std::endl;
}
ANSWER
It turns out that ecatmur's answer below works in most cases. In my specific situation, I adapted his solution to my real code, it worked in 2 out of 4 cases. In the two cases where it failed to work, it was a bit beyond the scope of the Mickey-Mouse example that I gave above. The closest explanation that I could find in SO which explains the compile-time errors I was getting is probably this post. The crux of the problem appeared to be related to what was happening inside my Worker code. In the two failed cases, I was doing output streaming of the subclasses' members based on what I was getting back from runtime reflection results in boost mirror. I think this is turned out to be a case of non-deducible context. I still don't understand why the solution in those two failed cases works exactly (why using a visitor in the form of a virtual method gets around the issue). Anyhow, I stumbled upon that approach and was trying to reduce the code some more (in those 4 cases), but in two of them, I couldn't really reduce that code any more without running into the non-deducible context issue.
Bar::getValues can be moved to Foo<Bar> using a CRTP downcast:
template< typename T >
struct Foo
{
static std::ostream& GetValues_Worker( std::ostream& os, T const& t )
{
// do boost mirror reflection stuff here
return os;
}
std::ostream& getValues( std::ostream& os ) const
{
return GetValues_Worker( os, *static_cast<T const *>(this) );
}
};
At this point you might as well combine the two methods:
template< typename T >
struct Foo
{
std::ostream& getValues( std::ostream& os ) const
{
T const &t = *static_cast<T const *>(this);
// do boost mirror reflection stuff here
return os;
}
};

Idiomatic use of std::rel_ops

What is the preferred method of using std::rel_ops to add the full set of relational operators to a class?
This documentation suggests a using namespace std::rel_ops, but this seems to be deeply flawed, as it would mean that including the header for the class implemented in this way would also add full relational operators to all other classes with a defined operator< and operator==, even if that was not desired. This has the potential to change the meaning of code in surprising ways.
As a side note - I have been using Boost.Operators to do this, but I am still curious about the standard library.
The way operator overloads for user defined classes was meant to work is via argument dependent lookup. ADL allows programs and libraries to avoid cluttering up the global namespace with operator overloads, but still allow convenient use of the operators; That is, without explicit namespace qualification, which is not possible to do with the infix operator syntax a + b and would instead require normal function syntax your_namespace::operator+ (a, b).
ADL, however, doesn't just search everywhere for any possible operator overload. ADL is restricted to look only at 'associated' classes and namespaces. The problem with std::rel_ops is that, as specified, this namespace can never be an associated namespace of any class defined outside the standard library, and therefore ADL cannot work with such user defined types.
However, if you're willing to cheat you can make std::rel_ops work.
Associated namespaces are defined in C++11 3.4.2 [basic.lookup.argdep] /2. For our purposes the important fact is that the namespace of which a base class is a member is an associated namespace of the inheriting class, and thus ADL will check those namespaces for appropriate functions.
So, if the following:
#include <utility> // rel_ops
namespace std { namespace rel_ops { struct make_rel_ops_work {}; } }
were to (somehow) find its way into a translation unit, then on supported implementations (see next section) you could then define your own class types like so:
namespace N {
// inherit from make_rel_ops_work so that std::rel_ops is an associated namespace for ADL
struct S : private std::rel_ops::make_rel_ops_work {};
bool operator== (S const &lhs, S const &rhs) { return true; }
bool operator< (S const &lhs, S const &rhs) { return false; }
}
And then ADL would work for your class type and would find the operators in std::rel_ops.
#include "S.h"
#include <functional> // greater
int main()
{
N::S a, b;
a >= b; // okay
std::greater<N::s>()(a, b); // okay
}
Of course adding make_rel_ops_work yourself technically causes the program to have undefined behavior because C++ does not allow user programs to add declarations to std. As an example of how that actually does matter and why, if you do this, you may want to go to the trouble of verifying that your implementation does in fact work properly with this addition, consider:
Above I show a declaration of make_rel_ops_work that follows #include <utility>. One might naively expect that including this here doesn't matter and that as long as the header is included sometime prior to the use of the operator overloads, then ADL will work. The spec of course makes no such guarantee and there are actual implementations where that is not the case.
clang with libc++, due to libc++'s use of inline namespaces, will (IIUC) consider that declaration of make_rel_ops_work to be in a distinct namespace from the namespace containing the <utility> operator overloads unless <utility>'s declaration of std::rel_ops comes first. This is because, technically, std::__1::rel_ops and std::rel_ops are distinct namespaces even if std::__1 is an inline namespace. But if clang sees that the original namespace declaration for rel_ops is in an inline namespace __1, then it will treat a namespace std { namespace rel_ops { declaration as extending std::__1::rel_ops rather than as a new namespace.
I believe this namespace extension behavior is a clang extension rather than specified by C++, so you may not even be able to rely on this in other implementations. In particular gcc does not behave this way, but fortunately libstdc++ doesn't use inline namespaces. If you don't want to rely on this extension then for clang/libc++ you can write:
#include <__config>
_LIBCPP_BEGIN_NAMESPACE_STD
namespace rel_ops { struct make_rel_ops_work {}; }
_LIBCPP_END_NAMESPACE_STD
but obviously then you'll need implementations for other libraries you use. My simpler declaration of make_rel_ops_work works for clang3.2/libc++, gcc4.7.3/libstdc++, and VS2012.
I think that the preferred technique is not to use std::rel_ops at
all. The technique used in boost::operator (link) seems to be the usual
solution.
Example:
#include "boost/operators.hpp"
class SomeClass : private boost::equivalent<SomeClass>, boost::totally_ordered<SomeClass>
{
public:
bool operator<(const SomeClass &rhs) const
{
return someNumber < rhs.someNumber;
}
private:
int someNumber;
};
int main()
{
SomeClass a, b;
a < b;
a > b;
a <= b;
a >= b;
a == b;
a != b;
}
The problem with adding the rel_ops namespace, regardless of whether you do it with a manual using namespace rel_ops; or whether you do it automatically as described in the answer by #bames53 is that adding the namespace can have unanticipated side effects on portions of your code. I found this myself just recently as I had been using the #bames53 solution for some time, but when I changed one of my container based operations to use a reverse_iterator instead of an iterator (within a multimap but I suspect it would be the same for any of the standard containers), suddenly I was getting compile errors when using != to compare two iterators. Ultimately I tracked it down to the fact that the code included the rel_ops namespace which was interfering with how reverse_iterators are defined.
Using boost would be a way to solve it, but as mentioned by #Tom not everyone is willing to use boost, myself included. So I implemented my own class to solve the problem, which I suspect is also how boost does it, but I didn't check the boost libraries to see.
Specifically, I have the following structure defined:
template <class T>
struct add_rel_ops {
inline bool operator!=(const T& t) const noexcept {
const T* self = static_cast<const T*>(this);
return !(*self == t);
}
inline bool operator<=(const T& t) const noexcept {
const T* self = static_cast<const T*>(this);
return (*self < t || *self == t);
}
inline bool operator>(const T& t) const noexcept {
const T* self = static_cast<const T*>(this);
return (!(*self == t) && !(*self < t));
}
inline bool operator>=(const T& t) const noexcept {
const T* self = static_cast<const T*>(this);
return !(*self < t);
}
};
To use this, when you define your class, say MyClass, you can inherit from this one to add the "missing" operators. Of course you need to define the == and < operators within MyClass (not shown below).
class MyClass : public add_rel_ops<MyClass> {
...stuff...
};
It is important that you include MyClass as the template argument. If you were to include a different class, say MyOtherClass, the static_cast would be almost certain to give you problems.
Note that my solution is assuming that the == and < operators are defined as const noexcept which is one of the requirements of my personal coding standards. If your standards are different, you would need to modify add_rel_ops accordingly.
In addition, if you are bothered by the use of static_cast, you can change them to be a dynamic_cast by adding
virtual ~add_rel_ops() noexcept = default;
to the add_rel_ops class in order to make it a virtual class. Of course, that will also force MyClass to be a virtual class which is why I do not take that approach.
It's not the nicest, but you can use using namespace std::rel_ops as an implementation detail for implementing the comparison operators on your type. For example:
template <typename T>
struct MyType
{
T value;
friend bool operator<(MyType const& lhs, MyType const& rhs)
{
// The type must define `operator<`; std::rel_ops doesn't do that
return lhs.value < rhs.value;
}
friend bool operator<=(MyType const& lhs, MyType const& rhs)
{
using namespace std::rel_ops;
return lhs.value <= rhs.value;
}
// ... all the other comparison operators
};
By using using namespace std::rel_ops;, we allow ADL to lookup operator<= if it is defined for the type, but fall back onto the one defined in std::rel_ops otherwise.
This is still a pain, though, as you still have to write a function for each of the comparison operators.

How to overload std::swap()

std::swap() is used by many std containers (such as std::list and std::vector) during sorting and even assignment.
But the std implementation of swap() is very generalized and rather inefficient for custom types.
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?
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);
// ...
}
};
Attention Mozza314
Here is a simulation of the effects of a generic std::algorithm calling std::swap, and having the user provide their swap in namespace std. As this is an experiment, this simulation uses namespace exp instead of namespace std.
// simulate <algorithm>
#include <cstdio>
namespace exp
{
template <class T>
void
swap(T& x, T& y)
{
printf("generic exp::swap\n");
T tmp = x;
x = y;
y = tmp;
}
template <class T>
void algorithm(T* begin, T* end)
{
if (end-begin >= 2)
exp::swap(begin[0], begin[1]);
}
}
// simulate user code which includes <algorithm>
struct A
{
};
namespace exp
{
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
// exercise simulation
int main()
{
A a[2];
exp::algorithm(a, a+2);
}
For me this prints out:
generic exp::swap
If your compiler prints out something different then it is not correctly implementing "two-phase lookup" for templates.
If your compiler is conforming (to any of C++98/03/11), then it will give the same output I show. And in that case exactly what you fear will happen, does happen. And putting your swap into namespace std (exp) did not stop it from happening.
Dave and I are both committee members and have been working this area of the standard for a decade (and not always in agreement with each other). But this issue has been settled for a long time, and we both agree on how it has been settled. Disregard Dave's expert opinion/answer in this area at your own peril.
This issue came to light after C++98 was published. Starting about 2001 Dave and I began to work this area. And this is the modern solution:
// simulate <algorithm>
#include <cstdio>
namespace exp
{
template <class T>
void
swap(T& x, T& y)
{
printf("generic exp::swap\n");
T tmp = x;
x = y;
y = tmp;
}
template <class T>
void algorithm(T* begin, T* end)
{
if (end-begin >= 2)
swap(begin[0], begin[1]);
}
}
// simulate user code which includes <algorithm>
struct A
{
};
void swap(A&, A&)
{
printf("swap(A, A)\n");
}
// exercise simulation
int main()
{
A a[2];
exp::algorithm(a, a+2);
}
Output is:
swap(A, A)
Update
An observation has been made that:
namespace exp
{
template <>
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
works! So why not use that?
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. :-(
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.
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)
{
// ...
}
}
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).
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)
While it's correct that one shouldn't generally add stuff to the std:: namespace, adding template specializations for user-defined types is specifically allowed. Overloading the functions is not. This is a subtle difference :-)
17.4.3.1/1
It is undefined for a C++ program to add declarations or definitions
to namespace std or namespaces with namespace std unless otherwise
specified. A program may add template specializations for any
standard library template to namespace std. Such a specialization
(complete or partial) of a standard library results in undefined
behaviour unless the declaration depends on a user-defined name of
external linkage and unless the template specialization meets the
standard library requirements for the original template.
A specialization of std::swap would look like:
namespace std
{
template<>
void swap(myspace::mytype& a, myspace::mytype& b) { ... }
}
Without the template<> bit it would be an overload, which is undefined, rather than a specialization, which is permitted. #Wilka's suggest approach of changing the default namespace may work with user code (due to Koenig lookup preferring the namespace-less version) but it's not guaranteed to, and in fact isn't really supposed to (the STL implementation ought to use the fully-qualified std::swap).
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).