C++ 20 dependent template in a concept

Viewed 98

I would be really grateful if somebody could explain why the below code does not compile due to 'associated constraints are not satisfied' / 'no matching overloaded function found' (MSVC 2022, 17.2.1).

The Listener concept below requires a template input param of an Update < V > where V matches the template param V of MySignal.

If I change the parameter of the listen(...) to take a Func it compiles - but my assumption is that the concept / lambda approach must resolve to exactly the same type - so why is the constraint not satisfied?

EDIT: So I made a rather silly copy and paste error on my initial code snippet (now corrected) that confused matters. My question could also have been worded better - the crux of what I am failing to understand is why it seems I can define a concept with a templated param in my requires clause (ie Update<V>) but the compiler subsequently rejects the below code as not satisfying constraints.

template <typename V>
struct Update {
    V val;
};

template <typename T, typename V>
concept Listener = requires(T t, Update<V> update)
{
    {
        t(update)
        } -> std::convertible_to<void>;
};

template <typename V>
struct MySignal {
    using UpdateV = Update<V>;
    using Func = std::function<void(UpdateV)>;

    void listen(Listener<UpdateV> auto&& listener) {
        listeners_.emplace_back(Func{ listener });
    }

    std::vector<Func> listeners_;
};

int main(int argc, char** argv)
{
    MySignal<int64_t> sig;
    sig.listen([](Update<int64_t> u) {
        std::cout << "Got a signal";
    });
}
1 Answers

Listener<UpdateV> - this is your issue I think. In the concept you already check Update<V> and now you pass UpdateV as the parameter V. So your concept ends up checking for an operator()(Update<Update<V>>).

Related