Skip to content

Latest commit

 

History

History
105 lines (80 loc) · 2.79 KB

303.md

File metadata and controls

105 lines (80 loc) · 2.79 KB
Info

Example

template<auto...> struct long_type {};

using long_type_t = decltype(
    []<auto... Ns>(std::index_sequence<Ns...>) {
        return long_type<Ns...>{};
    }
    (std::make_index_sequence<42>{})
);

// typename erasure
struct short_type_t : long_type_t{};

// generic typename erasure
template<class T> using typename_erasure = decltype([] {
    struct s : T { using T::T; }; // generated in the compiler as `$0::s` or similar
    return s{};
}());

int main() {
    assert(std::string_view{typeid(long_type_t).name()}.size() > 100); // long...
    assert(std::string_view{typeid(short_type_t).name()}.size() < 15); // short
    assert(std::string_view{typeid(typename_erasure<long_type_t>).name()}.size() < 25); // short
}

https://godbolt.org/z/heaKzY7To

Puzzle

  • Can you implement typename_erasure function which will erase all given types?
template<class... Ts>
[[nodiscard]] constexpr auto typename_erasure; // TODO


template<auto... Ns> struct long_type{ };
template<auto N> using long_type_t = decltype(
    []<auto... Ns>(std::index_sequence<Ns...>) {
        return long_type<Ns...>{};
    }
    (std::make_index_sequence<N>{})
);

#include <string_view>
#include <typeinfo>
[[nodiscard]] consteval auto type_name(auto) { return std::string_view{__PRETTY_FUNCTION__}; }

static_assert(std::size(type_name(typename_erasure<long_type_t<100>, long_type_t<200>>())) < 42);
static_assert(not std::is_base_of_v<long_type_t<300>, decltype(typename_erasure<long_type_t<100>, long_type_t<200>>())>);
static_assert(std::is_base_of_v<long_type_t<100>, decltype(typename_erasure<long_type_t<100>, long_type_t<200>>())>);
static_assert(std::is_base_of_v<long_type_t<200>, decltype(typename_erasure<long_type_t<100>, long_type_t<200>>())>);

https://godbolt.org/z/zhd716b3T

Solutions

template<class... Ts>
[[nodiscard]] constexpr auto typename_erasure()
{
    struct s : Ts... {
        s() = default;
        s(Ts &&...arg) : Ts(::std::forward<Ts>(arg)) ... {}
    };
    return s{};
}

https://godbolt.org/z/xjoe54Mxh

template<class... Ts>
[[nodiscard]] constexpr auto typename_erasure(){
    struct s : public Ts...{};
    return s{};
};

https://godbolt.org/z/e1zPh5GGs

template<class T> using typename_erasure_one = decltype([] {
    struct s : T { using T::T; };
    return s{};
}());

template<class... Ts>
[[nodiscard]] constexpr auto typename_erasure = [] {
    struct a : typename_erasure_one<Ts>...{};
    return a{};
};

https://godbolt.org/z/8hxM5h7a5