Created
October 16, 2023 00:06
-
-
Save mtao/12796c10a03f9973b793bc3887bc16cf to your computer and use it in GitHub Desktop.
Getting unique types + removing void from a sequence of types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <tuple> | |
#include <type_traits> | |
template <typename T, typename U> | |
struct concatenate_tuple {}; | |
template <typename... Ts, typename... Us> | |
struct concatenate_tuple<std::tuple<Ts...>, std::tuple<Us...>> { | |
using type = std::tuple<Ts..., Us...>; | |
}; | |
template <typename T, typename U> | |
using concatenate_tuple_t = typename concatenate_tuple<T, U>::type; | |
template <typename...> | |
struct make_unique { | |
using type = std::tuple<>; | |
}; | |
template <typename T> | |
struct make_unique<T> { | |
using type = std::tuple<T>; | |
}; | |
template <typename... Ts> | |
using make_unique_t = typename make_unique<Ts...>::type; | |
template <typename T, typename RemainingTuple> | |
struct make_unique_tuple {}; | |
template <typename T, typename... Ts> | |
struct make_unique_tuple<T, std::tuple<Ts...>> { | |
constexpr static bool t_is_unique = (!std::is_same_v<T, Ts> && ...); | |
using adding_t_type = | |
std::conditional_t<t_is_unique, std::tuple<T>, std::tuple<>>; | |
using type = concatenate_tuple_t<adding_t_type, make_unique_t<Ts...>>; | |
}; | |
template <typename T, typename... Ts> | |
struct make_unique<T, Ts...> { | |
using type = typename make_unique_tuple<T, std::tuple<Ts...>>::type; | |
}; | |
template <typename...> | |
struct remove_void { | |
using type = std::tuple<>; | |
}; | |
template <> | |
struct remove_void<void> { | |
using type = std::tuple<>; | |
}; | |
template <typename T> | |
struct remove_void<T> { | |
using type = std::tuple<T>; | |
}; | |
template <typename... Ts> | |
using remove_void_t = typename remove_void<Ts...>::type; | |
template <typename T, typename RemainingTuple> | |
struct remove_void_tuple {}; | |
template <typename T, typename... Ts> | |
struct remove_void_tuple<T, std::tuple<Ts...>> { | |
constexpr static bool t_not_void = !std::is_same_v<T, void>; | |
using adding_t_type = | |
std::conditional_t<t_not_void, std::tuple<T>, std::tuple<>>; | |
using type = concatenate_tuple_t<adding_t_type, remove_void_t<Ts...>>; | |
}; | |
template <typename T, typename... Ts> | |
struct remove_void<T, Ts...> { | |
using type = typename remove_void_tuple<T, std::tuple<Ts...>>::type; | |
}; | |
// | |
template <typename... Ts> | |
using make_unique_remove_void_t = // make_unique_t<Ts...>; | |
typename remove_void_tuple<void, make_unique_t<Ts...>>::type; | |
// from https://stackoverflow.com/questions/81870/is-it-possible-to-print-a-variables-type-in-standard-c | |
#include <iostream> | |
#include <type_traits> | |
#include <typeinfo> | |
#ifndef _MSC_VER | |
#include <cxxabi.h> | |
#endif | |
#include <cstdlib> | |
#include <memory> | |
#include <string> | |
template <class T> | |
std::string type_name() { | |
typedef typename std::remove_reference<T>::type TR; | |
std::unique_ptr<char, void (*)(void*)> own( | |
#ifndef _MSC_VER | |
abi::__cxa_demangle(typeid(TR).name(), nullptr, nullptr, nullptr), | |
#else | |
nullptr, | |
#endif | |
std::free); | |
std::string r = own != nullptr ? own.get() : typeid(TR).name(); | |
if (std::is_const<TR>::value) r += " const"; | |
if (std::is_volatile<TR>::value) r += " volatile"; | |
if (std::is_lvalue_reference<T>::value) | |
r += "&"; | |
else if (std::is_rvalue_reference<T>::value) | |
r += "&&"; | |
return r; | |
} | |
int main(int argc, char* argv[]) { | |
std::cout << type_name< // | |
make_unique_t<int, std::string, int, float, int, float, | |
float> // | |
>() | |
<< std::endl; | |
std::cout << type_name< // | |
make_unique_t<int> // | |
>() | |
<< std::endl; | |
std::cout << type_name< // | |
make_unique_t<> // | |
>() | |
<< std::endl; | |
std::cout << type_name< // | |
remove_void_t<int, std::string, void, int, float, int, | |
float, float, void> // | |
>() | |
<< std::endl; | |
std::cout << type_name< // | |
remove_void_t<int> // | |
>() | |
<< std::endl; | |
std::cout << type_name< // | |
remove_void_t<void, int> // | |
>() | |
<< std::endl; | |
std::cout << type_name< // | |
remove_void_t<int, void> // | |
>() | |
<< std::endl; | |
std::cout << type_name< // | |
remove_void_t<> // | |
>() | |
<< std::endl; | |
std::cout | |
<< type_name< // | |
make_unique_remove_void_t<int, std::string, void, int, float, | |
int, float, float, void> // | |
>() | |
<< std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment