我想要:
template<class ... T>
auto foo()
{
// ? magic ?
}
這樣:
(foo<int, char, bool>() == foo<char, int, bool>()) // True
(foo<int>() == foo<char>()) // False
換句話說,我希望 foo 為傳遞給它的型別組合回傳一個唯一的 id,而不是傳遞給它的型別的排列。
我的第一個想法是可能有某種方法可以在編譯時對引數包進行排序,但我不確定這究竟是如何作業的。
我目前的解決方案是這樣的:
// Precondition: Client must pass the parameters in alphabetical order to ensure the same result each time
template<class ... T>
std::type_index foo()
{
return std::make_type_index(typeid(std::tuple<T ... >));
}
這樣做的問題是,如果客戶端使用型別別名,它就不起作用。例如:
using my_type = char;
(foo<bool, int, my_type>() == foo<bool, char, int>()) // False
我的一個想法是為函式處理的每個新型別分配一個新的質數作為 id。然后我可以通過將它們的質數 id 相乘來為特定的型別組合分配一個唯一的 id。例如:
id of int = 2
id of bool = 3
id of char = 5
id of <int, bool, char> = 2 * 3 * 5 = 30
id of <bool, int, char> = 3 * 2 * 5 = 30
唯一的問題是我將如何為每種型別分配唯一的質數 ID,而不會導致運行時損失。
uj5u.com熱心網友回復:
使用 Boost.Hana:
#include <boost/hana/set.hpp>
#include <boost/hana/type.hpp>
template<typename... T>
constexpr auto foo() {
return boost::hana::make_set(boost::hana::type_c<T>...);
}
using my_type = char;
static_assert(foo<bool, int, my_type>() == foo<bool, char, int>());
uj5u.com熱心網友回復:
使用 Boost.Mp11:
template <typename T>
constexpr std::string_view type_name() {
return __PRETTY_FUNCTION__; // close enough
}
template <typename T, typename U>
using type_less = mp_bool<type_name<T>() < type_name<U>()>;
template <typename... Ts>
constexpr auto foo() {
return type_name<mp_sort<mp_list<Ts...>, type_less>>();
}
static_assert(foo<int, char>() == foo<char, int>());
uj5u.com熱心網友回復:
您可以使用 gcc /clang 的擴展名__PRETTY_FUNCTION__(__FUNCSIG__在 msvc 中)作為每種型別的識別符號并將它們保存到 中std::array,然后對其進行排序以獲得型別串列的唯一組合。
但是由于std::arrays不同大小的無法相互比較,我們還需要創建一個新型別 ( unique_id) 來包裝已排序的陣列并多載其operator==:
#include <algorithm>
#include <array>
#include <string_view>
template <class T>
constexpr std::string_view id() {
#ifdef __GNUC__
return __PRETTY_FUNCTION__;
#elif defined(_MSC_VER)
return __FUNCSIG__;
#endif
}
template<std::size_t N>
class unique_id {
std::array<std::string_view, N> value;
public:
constexpr unique_id(const std::array<std::string_view, N>& value) : value(value) { }
template<std::size_t M>
constexpr bool operator==(const unique_id<M>& other) const {
if constexpr (N == M) return value == other.value;
else return false;
}
};
template<class... Ts>
constexpr auto foo() {
std::array<std::string_view, sizeof...(Ts)> names{id<Ts>()...};
std::ranges::sort(names);
return unique_id(names);
}
static_assert(foo<int, char, bool>() == foo<char, int, bool>());
static_assert(foo<int>() != foo<char>());
演示。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/326448.html
上一篇:在Airflow中使用jinja2為KubernetesPodOperator構建串列
下一篇:模板成員函式語法
