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 requires-expression.
(NOTE Although there is a perfectly fine standard C++ concept for this, std::swappable
, this example uses swap
for exposition only. I'm not particularly looking to test whether something is actually swappable, I'm just trying to find a way to implement such a concept where a customization function has a default implementation in a known namespace, but might have overloads in an associated namespace.)
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 use it
using detail::Swappable;
// or redefine it
template<class T>
concept Swappable = detail::Swappable<T>;
You can put it inside a lambda:
template<class T>
concept Swappable = []{
using std::swap;
return requires(T& a, T& b) { swap(a, b); };
}();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With