c++c++20c++-conceptsrequires-expression

Is there a way to use a using-declaration inside a requires-expression


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>;

Solution

  • You can put it inside a lambda:

    template<class T>
    concept Swappable = []{
        using std::swap;
        return requires(T& a, T& b) { swap(a, b); };
    }();