[英]How do I compare tuples for equivalent types disregarding type order?
我正在尋找一種比較兩個元組以查看它們是否包含相同類型的方法。
類型的順序無關緊要。 只要兩個元組的類型之間存在一對一的映射,我就會認為它們是等效的。
這是我設置的一個小測試。
我在實現equivalent_types()
時遇到了麻煩:
#include <iostream>
#include <utility>
#include <tuple>
#include <functional>
template <typename T, typename U>
bool equivalent_types(T t, U u){
return (std::tuple_size<T>::value == std::tuple_size<U>::value);
//&& same types regardless of order
}
int main() {
//these tuples have the same size and hold the same types.
//regardless of the type order, I consider them equivalent.
std::tuple<int,float,char,std::string> a;
std::tuple<std::string,char,int,float> b;
std::cout << equivalent_types(a,b) << '\n'; //should be true
std::cout << equivalent_types(b,a) << '\n'; //should be true
//examples that do not work:
//missing a type (not enough types)
std::tuple<std::string,char,int> c;
//duplicate type (too many types)
std::tuple<std::string,char,int,float,float> d;
//wrong type
std::tuple<bool,char,int,float> e;
std::cout << equivalent_types(a,c) << '\n'; //should be false
std::cout << equivalent_types(a,d) << '\n'; //should be false
std::cout << equivalent_types(a,e) << '\n'; //should be false
}
通過計算兩個元組的類型,您可以執行以下操作:
template <typename T, typename Tuple>
struct type_counter;
template <typename T, typename ... Ts>
struct type_counter<T, std::tuple<Ts...>> :
std::integral_constant<std::size_t, (... + std::is_same<T, Ts>::value)> {};
template <typename Tuple1, typename Tuple2, std::size_t... Is>
constexpr bool equivalent_types(const Tuple1&, const Tuple2&, std::index_sequence<Is...>)
{
return (...
&& (type_counter<std::tuple_element_t<Is, Tuple1>, Tuple1>::value
== type_counter<std::tuple_element_t<Is, Tuple1>, Tuple2>::value));
}
template <typename Tuple1, typename Tuple2>
constexpr bool equivalent_types(const Tuple1& t1, const Tuple2& t2)
{
constexpr auto s1 = std::tuple_size<Tuple1>::value;
constexpr auto s2 = std::tuple_size<Tuple2>::value;
return s1 == s2
&& equivalent_types(t1, t2, std::make_index_sequence<std::min(s1, s2)>());
}
我使用c ++ 17來折疊表達式,但是可以很容易地將其重寫為constexpr函數。
使用Hana(與最新的Boost版本打包在一起),我們可以將每個元組類型轉換成一個映射,從類型到它們發生的次數,然后比較這些映射是否相等:
template <typename T, typename U>
bool equivalent_types(T t, U u) {
namespace hana = boost::hana;
auto f = [](auto m, auto&& e) {
auto k = hana::decltype_(&e);
return hana::insert(hana::erase_key(m, k),
hana::make_pair(k, hana::find(m, k).value_or(0) + 1));
};
return hana::fold(t, hana::make_map(), f) == hana::fold(u, hana::make_map(), f);
}
請注意,必須使用&e
作為hana::decltype_
的參數,以確保將例如int
和int&
視為不同類型(通過通用引用傳遞e
的同上)。
該代碼似乎可以按任何順序與參數一起使用。 false
結果是編譯器錯誤。 我對TMP不太滿意,但是它是100%的編譯時。. 我很喜歡關於如何清理它的一些建議。 直播: https : //godbolt.org/g/3RZaMQ
#include <tuple>
#include <type_traits>
using namespace std;
// This struct removes the first instance of TypeToRemove from the Tuple or 'returns' void if it isn't present
template<class TypeToRemove, class ProcessedTupleParts, class RemainingTuple, class=void>
struct RemoveType;
template<class T, class... ProcessedTupleParts, class TupleHead, class... TupleTail>
struct RemoveType<T, std::tuple<ProcessedTupleParts...>, std::tuple<TupleHead, TupleTail...>, enable_if_t<std::is_same<T, TupleHead>::value>> {
using RemovedType = std::tuple<ProcessedTupleParts..., TupleTail...>;
};
template<class T, class... ProcessedTupleParts, class TupleHead, class... TupleTail>
struct RemoveType<T, std::tuple<ProcessedTupleParts...>, std::tuple<TupleHead, TupleTail...>, enable_if_t<!std::is_same<T, TupleHead>::value>> {
using RemovedType = typename RemoveType<T, std::tuple<ProcessedTupleParts..., TupleHead>, std::tuple<TupleTail...>>::RemovedType;
};
template<class T, class... Anything>
struct RemoveType<T, std::tuple<Anything...>, std::tuple<>> {
using RemovedType = void;
};
template<class T1, class T2>
struct CompareTuples;
template<class T1Head, class... T1Tail, class T2>
struct CompareTuples<std::tuple<T1Head, T1Tail...>, T2> {
using Result = typename CompareTuples<std::tuple<T1Tail...>, typename RemoveType<T1Head, std::tuple<>, T2>::RemovedType>::Result;
};
template<>
struct CompareTuples<std::tuple<>, std::tuple<>> {
using Result = std::tuple<>;
};
template<class... T2Body>
struct CompareTuples<std::tuple<>, std::tuple<T2Body...>> {
using Result = void;
};
template<class T1>
struct CompareTuples<T1, void> {
using Result = void;
};
int main() {
RemoveType<int, std::tuple<>,
RemoveType<char, std::tuple<>, std::tuple<int, char>>::RemovedType>::RemovedType aa;
CompareTuples<std::tuple<int>, std::tuple<int>>::Result a;
CompareTuples<std::tuple<char, int>, std::tuple<int, char>>::Result b;
CompareTuples<std::tuple<char, int>, std::tuple<int, char, double>>::Result e;
CompareTuples<std::tuple<char, double, int>, std::tuple<int, char, double>>::Result f;
CompareTuples<std::tuple<char, double, int>, std::tuple<int, char>>::Result g;
CompareTuples<std::tuple<char>, std::tuple<int>>::Result c;
CompareTuples<std::tuple<int>, std::tuple<int, char>>::Result d;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.