I am studying concepts
in C++ 20, and came up with the need of defining a concept
using a previous defined concept
.
So, in the example below I expected f<pub_b>()
to generate a compiler error, since events_published
in pub_b
does not satisfy publisher
concept, as ev_2
does not satisfy event
concept.
It seems that using event
concept in publisher
concept has no effect.
g++ version
reports
g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
What am I doing wrong?
#include <concepts>
#include <tuple>
template <typename t>
concept event = requires {
std::default_initializable<t>;
std::copy_constructible<t>;
std::move_constructible<t>;
};
struct ev_1 {
ev_1() = default;
ev_1(const ev_1 &) = default;
ev_1(ev_1 &&) = default;
};
struct ev_2 {
ev_2() = delete;
ev_2(const ev_2 &) = default;
ev_2(ev_2 &&) = default;
};
template <typename t>
concept publisher = requires {
typename t::events_published;
requires[]<std::size_t... t_idx>(std::index_sequence<t_idx...>) {
return ((event<typename std::tuple_element_t<
t_idx, typename t::events_published>>)&&...);
}
(std::make_index_sequence<std::tuple_size_v<typename t::events_published>>());
};
struct pub_a {
using events_published = std::tuple<ev_1>;
};
struct pub_b {
using events_published = std::tuple<ev_2>;
};
template <publisher t_publisher> void f() {}
int main() {
f<pub_a>();
f<pub_b>();
return 0;
}
2
Answers
The
event
concept
requires morerequires
:There is no need to use a
requires
-clause for your concept as it is usually used to check the validity of an expression. Just simplyas
copy_constructible
already guaranteesmove_constructible
. If you also need the type to be copy-assignable, life will be easier