Основываясь на комментариях Кейси о PR , который привел к этому добавлению (спасибо Джастину), inline namespace
необходим для того, чтобы что-то подобное работало:
namespace N {
namespace detail {
// default implementation
template <typename T> void swap(T&, T& ) { ... }
struct swap_fn {
template <typename T>
void operator()(T& a, T& b) {
swap(a, b); // unqualified call, the default is in scope
}
};
}
// the object
inline namespace CPO { inline constexpr detail::swap_fn swap{}; } // #1
struct S { friend void swap(S&, S&) { ... } }; // #2
}
N::S a;
N::swap(a, a); // calls the CPO, which calls the friend function
Еслиобъект точки настройки swap
(на #1
) не находился в своем собственном пространстве имен, между cpo и нечленом friend
, объявленным для типа S
(на #2
), произошло бы столкновение имен.Они должны быть в разных пространствах имен.
Поместить CPO во встроенное пространство имен достаточно, потому что регулярный неквалифицированный или квалифицированный поиск никогда не найдет своп в #2
- он будет найден только ADL, что происходит только в swap_fn::operator()
.
Да, это круто.И сложный.