Example
#include <concepts>
struct movable {
constexpr movable(movable&&) = default;
constexpr auto operator=(movable &&) -> movable & = default;
};
static_assert(std::movable<movable>)
Puzzle
- Can you fulfill given types so that they will satisfy provided object concepts?
#include <concepts>
struct movable; // TODO
struct not_movable; // TODO
static_assert(not std::movable<not_movable>);
static_assert(std::movable<movable>);
struct copyable; // TODO
struct not_copyable; // TODO
static_assert(not std::copyable<not_copyable>);
static_assert(std::copyable<copyable>);
struct not_semiregular; // TODO
struct semiregular; // TODO
static_assert(not std::semiregular<not_semiregular>);
static_assert(std::semiregular<semiregular>);
struct not_regular; // TODO
struct regular; // TODO
static_assert(not std::regular<not_regular>);
static_assert(std::regular<regular>);
Solutions
#include <concepts>
struct movable {};
struct not_movable {
// Either of these works - both for completeness
not_movable(not_movable&&) = delete;
not_movable& operator=(not_movable&&) = delete;
};
static_assert(std::movable<movable>);
static_assert(not std::movable<not_movable>);
struct copyable {};
struct not_copyable {
// Either of these works - both for completeness
not_copyable(const not_copyable&) = delete;
not_copyable& operator=(const not_copyable&) = delete;
};
static_assert(std::copyable<copyable>);
static_assert(not std::copyable<not_copyable>);
struct semiregular {};
struct not_semiregular {
// Any of these works - all for completeness
constexpr not_semiregular(auto) {}
not_semiregular(const not_semiregular&) = delete;
not_semiregular& operator=(const not_semiregular&) = delete;
};
static_assert(std::semiregular<semiregular>);
static_assert(not std::semiregular<not_semiregular>);
struct regular {
constexpr bool operator==(const regular&) const = default;
};
struct not_regular {};
static_assert(std::regular<regular>);
static_assert(not std::regular<not_regular>);
#include <concepts>
struct movable{};
struct not_movable{
constexpr not_movable(not_movable&&) = delete;
constexpr auto operator=(not_movable &&) -> not_movable & = delete;
};
static_assert(not std::movable<not_movable>);
static_assert(std::movable<movable>);
struct copyable{};
struct not_copyable{
constexpr not_copyable(not_copyable&) = delete;
constexpr auto operator=(not_copyable &) -> not_copyable & = delete;
};
static_assert(not std::copyable<not_copyable>);
static_assert(std::copyable<copyable>);
struct not_semiregular{
constexpr not_semiregular(auto) {}
constexpr not_semiregular(not_semiregular&) = default;
constexpr auto operator=(not_semiregular &) -> not_semiregular & = default;
};
struct semiregular{};
static_assert(not std::semiregular<not_semiregular>);
static_assert(std::semiregular<semiregular>);
struct not_regular{};
struct regular{
constexpr bool operator==(regular const&) const = default;
};
static_assert(not std::regular<not_regular>);
static_assert(std::regular<regular>);
struct movable {};
struct not_movable{not_movable(not_movable&&)=delete;};
static_assert(not std::movable<not_movable>);
static_assert(std::movable<movable>);
struct copyable {};
struct not_copyable {not_copyable(const not_copyable&)=delete;};
static_assert(not std::copyable<not_copyable>);
static_assert(std::copyable<copyable>);
struct not_semiregular { not_semiregular()=delete; };
struct semiregular {};
static_assert(not std::semiregular<not_semiregular>);
static_assert(std::semiregular<semiregular>);
struct not_regular {};
struct regular {bool operator==(const regular&) const = default;};
static_assert(not std::regular<not_regular>);
static_assert(std::regular<regular>);
struct movable {};
struct not_movable {
constexpr not_movable(const not_movable&) = delete;
};
static_assert(not std::movable<not_movable>);
static_assert(std::movable<movable>);
struct copyable {};
struct not_copyable {
constexpr not_copyable(not_copyable&&) = default;
};
static_assert(not std::copyable<not_copyable>);
static_assert(std::copyable<copyable>);
struct not_semiregular { not_semiregular() = delete; }; // unnfortunately
struct semiregular {};
static_assert(not std::semiregular<not_semiregular>);
static_assert(std::semiregular<semiregular>);
struct not_regular {};
struct regular {
friend constexpr auto operator==(regular, regular) -> bool = default;
};
static_assert(not std::regular<not_regular>);
static_assert(std::regular<regular>);
struct movable {};
struct not_movable {
not_movable(not_movable &&) = delete;
};
static_assert(not std::movable<not_movable>);
static_assert(std::movable<movable>);
struct copyable {};
struct not_copyable {
not_copyable(const not_copyable &) = delete;
};
static_assert(not std::copyable<not_copyable>);
static_assert(std::copyable<copyable>);
struct semiregular {};
struct not_semiregular {
not_semiregular() = delete;
};
static_assert(not std::semiregular<not_semiregular>);
static_assert(std::semiregular<semiregular>);
struct not_regular {};
struct regular {
constexpr auto operator==(const regular &) const -> bool = default;
};
static_assert(not std::regular<not_regular>);
static_assert(std::regular<regular>);
struct movable {};
struct not_movable{
constexpr auto operator=(not_movable &&) = delete;
};
static_assert(not std::movable<not_movable>);
static_assert(std::movable<movable>);
struct copyable {};
struct not_copyable {
constexpr not_copyable(not_copyable &) = delete;
};
static_assert(not std::copyable<not_copyable>);
static_assert(std::copyable<copyable>);
struct semiregular {};
struct not_semiregular {
constexpr not_semiregular(not_semiregular &) = delete;
constexpr not_semiregular() = delete;
};
static_assert(not std::semiregular<not_semiregular>);
static_assert(std::semiregular<semiregular>);
struct not_regular{};
struct regular{
constexpr bool operator<=>(const regular&) const = default;
};
static_assert(not std::regular<not_regular>);
static_assert(std::regular<regular>);
struct movable {
constexpr movable(movable&&) = default;
constexpr auto operator=(movable&&) -> movable& = default;
};
struct not_movable {
constexpr not_movable(not_movable&&) = delete;
constexpr auto operator=(not_movable&&) -> not_movable& = delete;
};
static_assert(not std::movable<not_movable>);
static_assert(std::movable<movable>);
struct copyable {
constexpr copyable(const copyable&) = default;
constexpr auto operator=(const copyable&) -> copyable& = default;
};
struct not_copyable {
constexpr not_copyable(const not_copyable&) = delete;
constexpr auto operator=(const not_copyable&) -> not_copyable& = delete;
};
static_assert(not std::copyable<not_copyable>);
static_assert(std::copyable<copyable>);
struct not_semiregular {
constexpr not_semiregular() = delete;
constexpr not_semiregular(const not_semiregular&) = delete;
constexpr auto operator=(const not_semiregular&) -> not_semiregular& = default;
};
struct semiregular {
constexpr semiregular() = default;
constexpr semiregular(const semiregular&) = default;
constexpr auto operator=(const semiregular&) -> semiregular& = default;
};
static_assert(not std::semiregular<not_semiregular>);
static_assert(std::semiregular<semiregular>);
struct not_regular {
constexpr not_regular() = delete;
constexpr not_regular(const not_regular&) = delete;
constexpr auto operator==(const not_regular&) const -> bool = delete;
};
struct regular {
constexpr regular() = default;
constexpr regular(const regular&) = default;
constexpr auto operator==(const regular&) const -> bool = default;
};
static_assert(not std::regular<not_regular>);
static_assert(std::regular<regular>);
struct movable{
constexpr movable() = delete;
constexpr movable(const movable &) = delete;
constexpr movable(movable &&) = default;
constexpr auto operator=(movable &&) -> movable& = default;
constexpr auto operator=(const movable &) -> movable& = delete;
constexpr auto operator==(const movable &) const -> bool = delete;
};
struct not_movable{
constexpr not_movable() = default;
constexpr not_movable(const not_movable &) = default;
constexpr not_movable(not_movable &&) = delete;
constexpr auto operator=(not_movable &&) -> not_movable& = delete;
constexpr auto operator=(const not_movable &) -> not_movable& = default;
constexpr auto operator==(const not_movable &) const -> bool = default;
};
static_assert(not std::movable<not_movable>);
static_assert(std::movable<movable>);
struct copyable{
constexpr copyable() = delete;
constexpr copyable(const copyable &) = default;
constexpr copyable(copyable &&) = default;
constexpr auto operator=(copyable &&) -> copyable& = default;
constexpr auto operator=(const copyable &) -> copyable& = default;
constexpr auto operator==(const copyable &) const -> bool = delete;
};
struct not_copyable{
constexpr not_copyable() = default;
constexpr not_copyable(const not_copyable &) = delete;
constexpr not_copyable(not_copyable &&) = delete;
constexpr auto operator=(not_copyable &&) -> not_copyable& = delete;
constexpr auto operator=(const not_copyable &) -> not_copyable& = delete;
constexpr auto operator==(const not_copyable &) const -> bool = default;
};
static_assert(not std::copyable<not_copyable>);
static_assert(std::copyable<copyable>);
struct not_semiregular{
constexpr not_semiregular() = delete;
constexpr not_semiregular(const not_semiregular &) = delete;
constexpr not_semiregular(not_semiregular &&) = delete;
constexpr auto operator=(not_semiregular &&) -> not_semiregular& = delete;
constexpr auto operator=(const not_semiregular &) -> not_semiregular& = delete;
constexpr auto operator==(const not_semiregular &) const -> bool = default;
};
struct semiregular{
constexpr semiregular() = default;
constexpr semiregular(const semiregular &) = default;
constexpr semiregular(semiregular &&) = default;
constexpr auto operator=(semiregular &&) -> semiregular& = default;
constexpr auto operator=(const semiregular &) -> semiregular& = default;
constexpr auto operator==(const semiregular &) const -> bool = delete;
};
static_assert(not std::semiregular<not_semiregular>);
static_assert(std::semiregular<semiregular>);
struct not_regular{
constexpr not_regular() = delete;
constexpr not_regular(const not_regular &) = delete;
constexpr not_regular(not_regular &&) = delete;
constexpr auto operator=(not_regular &&) -> not_regular& = delete;
constexpr auto operator=(const not_regular &) -> not_regular& = delete;
constexpr auto operator==(const not_regular &) const -> bool = delete;
};
struct regular{
constexpr regular() = default;
constexpr regular(const regular &) = default;
constexpr regular(regular &&) = default;
constexpr auto operator=(regular &&) -> regular& = default;
constexpr auto operator=(const regular &) -> regular& = default;
constexpr auto operator==(const regular &) const -> bool = default;
};
static_assert(not std::regular<not_regular>);
static_assert(std::regular<regular>);
struct movable {};
struct not_movable {
not_movable(not_movable &&) = delete;
};
static_assert(not std::movable<not_movable>);
static_assert(std::movable<movable>);
struct copyable {};
struct not_copyable {
not_copyable(const not_copyable&) = delete;
};
static_assert(not std::copyable<not_copyable>);
static_assert(std::copyable<copyable>);
struct not_semiregular {
not_semiregular(int) {}
};
struct semiregular {};
static_assert(not std::semiregular<not_semiregular>);
static_assert(std::semiregular<semiregular>);
struct not_regular {};
struct regular {
constexpr bool operator==(const regular&) const = default;
};
static_assert(not std::regular<not_regular>);
static_assert(std::regular<regular>);
struct movable{};
struct not_movable{
constexpr not_movable(not_movable&&) = delete;
};
static_assert(not std::movable<not_movable>);
static_assert(std::movable<movable>);
struct copyable{};
struct not_copyable{
constexpr not_copyable(const not_copyable&) = delete;
};
static_assert(not std::copyable<not_copyable>);
static_assert(std::copyable<copyable>);
struct not_semiregular{
constexpr not_semiregular() = delete;
};
struct semiregular{};
static_assert(not std::semiregular<not_semiregular>);
static_assert(std::semiregular<semiregular>);
struct not_regular{};
struct regular{
constexpr auto operator==(const regular&) const -> bool = default;
};
static_assert(not std::regular<not_regular>);
static_assert(std::regular<regular>);
struct movable {
constexpr movable(movable&&) = default;
constexpr auto operator=(movable &&) -> movable & = default;
};
struct not_movable {
constexpr not_movable(not_movable&&) = delete;
constexpr auto operator=(not_movable &&) -> not_movable & = delete;
};
static_assert(not std::movable<not_movable>);
static_assert(std::movable<movable>);
struct copyable {
constexpr copyable(const copyable&) = default;
constexpr copyable(copyable&&) = default;
constexpr auto operator=(const copyable &) -> copyable & = default;
constexpr auto operator=(copyable &&) -> copyable & = default;
};
struct not_copyable {
constexpr not_copyable(const not_copyable&) = delete;
constexpr not_copyable(not_copyable&&) = delete;
constexpr auto operator=(const not_copyable &) -> not_copyable & = delete;
constexpr auto operator=(not_copyable &&) -> not_copyable & = delete;
};
static_assert(not std::copyable<not_copyable>);
static_assert(std::copyable<copyable>);
struct semiregular {
constexpr semiregular() = default;
constexpr semiregular(const semiregular&) = default;
constexpr semiregular(semiregular&&) = default;
constexpr auto operator=(const semiregular &) -> semiregular & = default;
constexpr auto operator=(semiregular &&) -> semiregular & = default;
};
struct not_semiregular {
constexpr not_semiregular() = delete;
constexpr not_semiregular(const not_semiregular&) = delete;
constexpr not_semiregular(not_semiregular&&) = delete;
constexpr auto operator=(const not_semiregular &) -> not_semiregular & = delete;
constexpr auto operator=(not_semiregular &&) -> not_semiregular & = delete;
};
static_assert(std::semiregular<semiregular>);
static_assert(not std::semiregular<not_semiregular>);
struct regular {
constexpr regular() = default;
constexpr regular(const regular&) = default;
constexpr regular(regular&&) = default;
constexpr auto operator=(const regular &) -> regular & = default;
constexpr auto operator=(regular &&) -> regular & = default;
constexpr auto operator==(const regular&) const -> bool = default;
};
struct not_regular {
constexpr not_regular() = delete;
constexpr not_regular(const not_regular&) = delete;
constexpr not_regular(not_regular&&) = delete;
constexpr auto operator=(const not_regular &) -> not_regular & = delete;
constexpr auto operator=(not_regular &&) -> not_regular & = delete;
constexpr auto operator==(const not_regular&) const -> bool = delete;
};
static_assert(std::regular<regular>);
static_assert(not std::regular<not_regular>);