Skip to content

Latest commit

 

History

History
330 lines (257 loc) · 14.2 KB

203.md

File metadata and controls

330 lines (257 loc) · 14.2 KB
Info

Example

static_assert(not std::is_same_v<char, signed char>);
static_assert(std::is_same_v<int, signed int>);

static_assert(not std::is_same_v<char, unsigned char>);
static_assert(not std::is_same_v<int, unsigned int>);

https://godbolt.org/z/ccah6j

Puzzle

  • Can you implement unique_types concept which is satisfied when all given types are unique and a foo function which only allows to take unique arguments?
template<class... Ts>
/*TODO */ concept unique_types = false;

static_assert(unique_types<char>);
static_assert(unique_types<signed char>);
static_assert(unique_types<signed, char>);
static_assert(unique_types<unsigned char>);
static_assert(unique_types<char, signed char>);
static_assert(unique_types<signed char, char>);
static_assert(unique_types<char, signed char, unsigned char>);
static_assert(unique_types<std::byte, char, signed char, unsigned char>);

static_assert(not unique_types<signed char, signed char>);
static_assert(not unique_types<char, signed, char>);
static_assert(not unique_types<char, signed, char, char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, std::byte, char, signed char, unsigned char>);
static_assert(not unique_types<std::int8_t, std::uint8_t, std::byte, char, signed char, unsigned char>);

/*TODO*/ constexpr auto foo(...) { }

static_assert([](auto... args) { return requires { foo(args...); }; }(char{}));
static_assert([](auto... args) { return requires { foo(args...); }; }(char{}, signed{}));
static_assert([](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}));

static_assert(not [](auto... args) { return requires { foo(args...); }; }(char{}, char{}));
static_assert(not [](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}, (signed char){}));

https://godbolt.org/z/5v1Kbx

Solutions

#include <type_traits>
#include <cstddef>
#include <cstdint>
#include <boost/mp11/list.hpp>
#include <boost/mp11/set.hpp>

template<class... Ts>
concept unique_types = boost::mp11::mp_is_set<boost::mp11::mp_list<Ts...>>::value;

static_assert(unique_types<char>);
static_assert(unique_types<signed char>);
static_assert(unique_types<signed, char>);
static_assert(unique_types<unsigned char>);
static_assert(unique_types<char, signed char>);
static_assert(unique_types<signed char, char>);
static_assert(unique_types<char, signed char, unsigned char>);
static_assert(unique_types<std::byte, char, signed char, unsigned char>);

static_assert(not unique_types<signed char, signed char>);
static_assert(not unique_types<char, signed, char>);
static_assert(not unique_types<char, signed, char, char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, std::byte, char, signed char, unsigned char>);
static_assert(not unique_types<std::int8_t, std::uint8_t, std::byte, char, signed char, unsigned char>);

template<class... Ts>
constexpr auto foo(Ts...) requires unique_types<Ts...> { }

static_assert([](auto... args) { return requires { foo(args...); }; }(char{}));
static_assert([](auto... args) { return requires { foo(args...); }; }(char{}, signed{}));
static_assert([](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}));

static_assert(not [](auto... args) { return requires { foo(args...); }; }(char{}, char{}));
static_assert(not [](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}, (signed char){}));

https://godbolt.org/z/P9n4WE

template <typename...> constexpr bool unique_head = true;
template <typename T, typename... Ts>
constexpr bool unique_head<T, Ts...> = ((not std::is_same_v<T, Ts>) and ...) and unique_head<Ts...>;

template <typename... Ts>
concept unique_types = unique_head<Ts...>;

static_assert(unique_types<char>);
static_assert(unique_types<signed char>);
static_assert(unique_types<signed, char>);
static_assert(unique_types<unsigned char>);
static_assert(unique_types<char, signed char>);
static_assert(unique_types<signed char, char>);
static_assert(unique_types<char, signed char, unsigned char>);
static_assert(unique_types<std::byte, char, signed char, unsigned char>);

static_assert(not unique_types<signed char, signed char>);
static_assert(not unique_types<char, signed, char>);
static_assert(not unique_types<char, signed, char, char>);
static_assert(not unique_types<signed, char, char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, std::byte, char, signed char, unsigned char>);
static_assert(not unique_types<std::int8_t, std::uint8_t, std::byte, char, signed char, unsigned char>);

template <typename... Ts> requires unique_types<Ts...>
constexpr auto foo(Ts&&...) { }

static_assert([](auto... args) { return requires { foo(args...); }; }(char{}));
static_assert([](auto... args) { return requires { foo(args...); }; }(char{}, signed{}));
static_assert([](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}));

static_assert(not [](auto... args) { return requires { foo(args...); }; }(char{}, char{}));
static_assert(not [](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}, (signed char){}));

https://godbolt.org/z/MxPzz3

template<class ...Ts> bool constexpr unique_types_impl = false;
template<class T1> bool constexpr unique_types_impl<T1> = true;
template<class T, class ...Ts>
bool constexpr unique_types_impl<T, Ts...> =
    (!std::is_same_v<T, Ts> && ... ) && unique_types_impl<Ts...>;

template<class... Ts> concept unique_types = unique_types_impl<Ts...>;

static_assert(unique_types<char>);
static_assert(unique_types<signed char>);
static_assert(unique_types<signed, char>);
static_assert(unique_types<unsigned char>);
static_assert(unique_types<char, signed char>);
static_assert(unique_types<signed char, char>);
static_assert(unique_types<char, signed char, unsigned char>);
static_assert(unique_types<std::byte, char, signed char, unsigned char>);

static_assert(not unique_types<signed char, signed char>);
static_assert(not unique_types<char, signed, char>);
static_assert(not unique_types<char, signed, char, char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, std::byte, char, signed char, unsigned char>);
static_assert(not unique_types<std::int8_t, std::uint8_t, std::byte, char, signed char, unsigned char>);

template<class ...Ts>
constexpr auto foo(Ts...) requires unique_types<Ts...> {}

static_assert([](auto... args) { return requires { foo(args...); }; }(char{}));
static_assert([](auto... args) { return requires { foo(args...); }; }(char{}, signed{}));
static_assert([](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}));

static_assert(not [](auto... args) { return requires { foo(args...); }; }(char{}, char{}));
static_assert(not [](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}, (signed char){}));

https://godbolt.org/z/hcE91b

template <typename T, typename... Ts>
constexpr bool are_unique() {
    if constexpr (sizeof...(Ts) == 0)
        return true;
    else
        return are_unique<Ts...>()
           and not boost::mp11::mp_contains<boost::mp11::mp_list<Ts...>, T>::value;
}

template<class... Ts>
concept unique_types = are_unique<Ts...>();

static_assert(unique_types<char>);
static_assert(unique_types<signed char>);
static_assert(unique_types<signed, char>);
static_assert(unique_types<unsigned char>);
static_assert(unique_types<char, signed char>);
static_assert(unique_types<signed char, char>);
static_assert(unique_types<char, signed char, unsigned char>);
static_assert(unique_types<std::byte, char, signed char, unsigned char>);

static_assert(not unique_types<signed char, signed char>);
static_assert(not unique_types<char, signed, char>);
static_assert(not unique_types<char, signed, char, char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, std::byte, char, signed char, unsigned char>);
static_assert(not unique_types<std::int8_t, std::uint8_t, std::byte, char, signed char, unsigned char>);

template <typename... Ts>
constexpr auto foo(Ts&&...)
requires unique_types<Ts...>
{}

static_assert([](auto... args) { return requires { foo(args...); }; }(char{}));
static_assert([](auto... args) { return requires { foo(args...); }; }(char{}, signed{}));
static_assert([](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}));

static_assert(not [](auto... args) { return requires { foo(args...); }; }(char{}, char{}));
static_assert(not [](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}, (signed char){}));

https://godbolt.org/z/bhY15f

template<class... Ts>
concept unique_types = std::is_same_v<mp_list<Ts...>, mp_unique<mp_list<Ts...>>>;

static_assert(unique_types<char>);
static_assert(unique_types<signed char>);
static_assert(unique_types<signed, char>);
static_assert(unique_types<unsigned char>);
static_assert(unique_types<char, signed char>);
static_assert(unique_types<signed char, char>);
static_assert(unique_types<char, signed char, unsigned char>);
static_assert(unique_types<std::byte, char, signed char, unsigned char>);

static_assert(not unique_types<signed char, signed char>);
static_assert(not unique_types<char, signed, char>);
static_assert(not unique_types<char, signed, char, char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, std::byte, char, signed char, unsigned char>);
static_assert(not unique_types<std::int8_t, std::uint8_t, std::byte, char, signed char, unsigned char>);

template<class... Ts> requires unique_types<Ts...>
constexpr auto foo(Ts...) { }

static_assert([](auto... args) { return requires { foo(args...); }; }(char{}));
static_assert([](auto... args) { return requires { foo(args...); }; }(char{}, signed{}));
static_assert([](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}));

static_assert(not [](auto... args) { return requires { foo(args...); }; }(char{}, char{}));
static_assert(not [](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}, (signed char){}));

https://godbolt.org/z/haeEd6

template<class... Ts>
concept unique_types = std::is_same_v<mp_unique_if<mp_list<Ts...>, std::is_same>, mp_list<Ts...>>;

static_assert(unique_types<char>);
static_assert(unique_types<signed char>);
static_assert(unique_types<signed, char>);
static_assert(unique_types<unsigned char>);
static_assert(unique_types<char, signed char>);
static_assert(unique_types<signed char, char>);
static_assert(unique_types<char, signed char, unsigned char>);
static_assert(unique_types<std::byte, char, signed char, unsigned char>);

static_assert(not unique_types<signed char, signed char>);
static_assert(not unique_types<char, signed, char>);
static_assert(not unique_types<char, signed, char, char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, std::byte, char, signed char, unsigned char>);
static_assert(not unique_types<std::int8_t, std::uint8_t, std::byte, char, signed char, unsigned char>);

template<typename... T>
constexpr auto foo(T &&... t) requires unique_types<T...> { }

static_assert([](auto... args) { return requires { foo(args...); }; }(char{}));
static_assert([](auto... args) { return requires { foo(args...); }; }(char{}, signed{}));
static_assert([](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}));

static_assert(not [](auto... args) { return requires { foo(args...); }; }(char{}, char{}));
static_assert(not [](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}, (signed char){}));

https://godbolt.org/z/Knqxzq

template <typename...>
constexpr bool unique = true;

template <typename T, typename... Ts>
constexpr bool unique<T, Ts...> = (!std::is_same_v<T, Ts> && ...) && unique<Ts...>;

template<class... Ts>
concept unique_types = unique<Ts...>;

static_assert(unique_types<char>);
static_assert(unique_types<signed char>);
static_assert(unique_types<signed, char>);
static_assert(unique_types<unsigned char>);
static_assert(unique_types<char, signed char>);
static_assert(unique_types<signed char, char>);
static_assert(unique_types<char, signed char, unsigned char>);
static_assert(unique_types<std::byte, char, signed char, unsigned char>);

static_assert(not unique_types<signed char, signed char>);
static_assert(not unique_types<char, signed, char>);
static_assert(not unique_types<char, signed, char, char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, unsigned char>);
static_assert(not unique_types<std::uint8_t, std::byte, char, signed char, unsigned char>);
static_assert(not unique_types<std::int8_t, std::uint8_t, std::byte, char, signed char, unsigned char>);

template< typename ...Ts>
constexpr auto foo(Ts...) requires unique_types<Ts...> {}

static_assert([](auto... args) { return requires { foo(args...); }; }(char{}));
static_assert([](auto... args) { return requires { foo(args...); }; }(char{}, signed{}));
static_assert([](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}));

static_assert(not [](auto... args) { return requires { foo(args...); }; }(char{}, char{}));
static_assert(not [](auto... args) { return requires { foo(args...); }; }((signed char){}, char{}, (signed char){}));

https://godbolt.org/z/dbGMdY