I want to test whether a type can be passed to some function, but I'd like to use ADL on the function lookup and include a function from a certain namespace.
Consider this code:
#include <utility>
#include <vector>
template<class T>
concept Swappable = requires(T& a, T&b)
{
swap(a,b);
};
static_assert(Swappable<std::vector<int>>); // #1
static_assert(Swappable<int>); // #2
#1 succeeds, it finds std::swap
because std
is an associated namespace of std::vector<int>
. But #2 fails, a built-in type has no associated namespace.
How would I write something like:
template<class T>
concept Swappable = requires(T& a, T&b)
{
using std::swap; // illegal
swap(a,b);
};
AFAIK, you're not allowed to use a using-declaration inside a required expression.
EDIT As a workaround, I can implement the concept in a separate namespace where the names are pulled in. Not too happy about it but it works.
namespace detail
{
using std::swap;
template<class T>
concept Swappable = requires(T& a, T&b)
{
swap(a,b);
};
}
// and then either uses it
using detail::Swappable;
// or redefine it
template<class T>
concept Swappable = detail::Swappable<T>;
CodePudding user response:
Avoid using old using
-based idioms. Instead, use the customization point equivalents like ranges::swap
.
That is, you should not require users to use using
-based idioms in their code. Provide a customization point object that does what it needs to. The operator()
overloads/templates can be constrained to create the effect of the using
idiom without requiring the user to actually invoke using
.
ranges::swap
is a good example of how this gets done.
CodePudding user response:
You can put it inside a lambda:
template<class T>
concept Swappable = []{
using std::swap;
return requires(T& a, T& b) { swap(a, b); };
}();