The established idiom for invoking swap
is:
using std::swap
swap(foo, bar);
This way, swap
can be overloaded for user
Using a using
-declaration like that is the correct way IMO. It's also what the standard does with the range for loop: if there is no begin
or end
members present then it will call begin(x)
and end(x)
with std
as an associated namespace (i.e. it will find std::begin
and std::end
if ADL doesn't find non-member begin
and end
).
If you find that writing using std::begin; using std::end;
all the time is tedious then you can use the adl_begin
and adl_end
functions below:
namespace aux {
using std::begin;
using std::end;
template
auto adl_begin(T&& x) -> decltype(begin(std::forward(x)));
template
auto adl_end(T&& x) -> decltype(end(std::forward(x)));
template
constexpr bool is_array()
{
using type = typename std::remove_reference::type;
return std::is_array::value;
}
} // namespace aux
template()>::type>
auto adl_begin(T&& x) -> decltype(aux::adl_begin(std::forward(x)))
{
using std::begin;
return begin(std::forward(x));
}
template()>::type>
auto adl_end(T&& x) -> decltype(aux::adl_end(std::forward(x)))
{
using std::end;
return end(std::forward(x));
}
template
T* adl_begin(T (&x)[N])
{
return std::begin(x);
}
template
T* adl_end(T (&x)[N])
{
return std::end(x);
}
This code is pretty monstrous. Hopefully with C++14 this can become less arcane:
template
concept bool Not_array()
{
using type = std::remove_reference_t;
return !std::is_array::value;
}
decltype(auto) adl_begin(Not_array&& x)
{
using std::begin;
return begin(std::forward(x));
}
decltype(auto) adl_end(Not_array&& x)
{
using std::end;
return end(std::forward(x));
}
template
T* adl_begin(T (&x)[N])
{
return std::begin(x);
}
template
T* adl_end(T (&x)[N])
{
return std::end(x);
}