C++20 Concepts: Require that an object has a method with further requirements on parameters and return value

Viewed 84

Say I want to specify that an object must have a method map(...) which maps a forward_range to another (possibly different) forward_range. How can I express that in a concept?

For instance, the following struct should be accepted:

struct Mapper{
    std::vector<double> map(std::list<int> args);
};

I have seen this question: C++ Concepts - Can I have a constraint requiring a function be present in a class? but I don't know how to use further concepts on argument and return types instead of using specific types.

EDIT: I have now also seen this question: How can unspecified types be used in C++20 'requires' expressions? However, it still does not help in my case. I will be more specific.

Let's assume I want to create a set of operators that operate on maps:

template<Map T1, Map T2>
class Chain {
    const T1& map1;
    const T2& map2;
public:
    Chain(const T1& map1, const T2& map2)
        :map1{ map1 }, map2{ map2 } {}

    template<forward_range T>
    auto map(T input) const {
        return map2(map1(input));
    }
};

template<Map T1, Map T2>
auto operator| (const T1& map1, const T2& map2) {
    return Chain(map1, map2);
}

Now I want this operator| to only operate on objects, that have a map function which maps from an argument which is some kind of forward_range to a return value which is also some kind of forward_range.

After some research I think this is somewhat abusing concepts as interfaces which should actually be done with a Map base class. But I don't know how to define these very generic requirements on the map method there either and I also want to learn concepts.

Note that there is also this conceptual problem of inverting the strength of requirements on parameters. If the constraint semantically says "Accept objects with a map method that takes any kind of forward_range as argument and returns any kind of forward_range.", this is a very strict requirement and I don't actually need the map method to be able to handle any arbitrary kind of (i.e. all kinds of) forward_range, just that whatever kind of argument it accepts must be a kind of forward_range. (I hope this also addresses @Caleth's comment)

0 Answers
Related