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

Time:12-03

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); };
}();
  • Related