В range-v3 все функции являются действительно глобальными объектами функций в встроенное пространство имен:
#if RANGES_CXX_INLINE_VARIABLES < RANGES_CXX_INLINE_VARIABLES_17 #define RANGES_INLINE_VARIABLE(type, name) \ inline namespace function_objects \ { \ inline namespace \ { \ constexpr auto &name = ::ranges::static_const<type>::value; \ } \ } #else // RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17 #define RANGES_INLINE_VARIABLE(type, name) \ inline namespace function_objects \ { \ inline constexpr type name{}; \ } #endif // RANGES_CXX_INLINE_VARIABLES
Какова цель function_objects
Пространство имен? Насколько я могу судить, на него нет ссылок нигде в библиотеке.
Основываясь на комментариях Кейси о 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()
,
Да, это довольно круто. И сложный.
Других решений пока нет …