我们假设我们有以下三种结构。
struct T1
{
using type = std::tuple<A1, A2, A3>;
}
struct T2
{
using type = std::tuple<A1, A2>;
}
struct T3
{
using type = std::tuple<A1>;
}
然后我创建一个元组,其中包含以下类型的实例:
std::tuple<T1, T2, T3> types;
现在是棘手的部分 - 我将如何创建这样的元组
std::tuple<std::tuple<T1&, T2&, T3&>, std::tuple<T1&, T2&>, std::tuple<T1&>>
出于'类型'元组中的哪个......
1)...第一个元组包含对嵌套typedef包含A1的所有元素的引用
2)...第二个元组包含一个引用所有嵌套typedef包含A2
的元素3)...第三个元组包含一个引用所有嵌套typedef包含A3
的元素我把我想要做的一个小例子放在一起,请记住这段代码还没有用,但它应该让你更好地理解我想要做的事情。
#include <iostream>
#include <tuple>
#include <type_traits>
#include <utility>
namespace util
{
template<typename Function, typename Tuple>
void for_each(Function&& function, Tuple&& tuple)
{
std::apply([&function](auto&&... xs){ (function(std::forward<decltype(xs)>(xs)), ...); }, std::forward<Tuple>(tuple));
}
}
namespace tl
{
template<typename T, typename Tuple>
struct tuple_contains;
template<typename T, typename Tuple, typename = std::make_index_sequence<std::tuple_size_v<Tuple>>>
struct tuple_index;
template<typename T, typename ...Ts>
struct tuple_contains<T, std::tuple<Ts...>>
: std::bool_constant<(std::is_same_v<T, Ts> || ...)>
{};
template<typename T, typename ...Ts, std::size_t ...Is>
struct tuple_index<T, std::tuple<Ts...>, std::index_sequence<Is...>>
: std::integral_constant<std::size_t, ((static_cast<std::size_t>(std::is_same_v<T, Ts>) * Is) + ...)>
{};
template<typename T, typename Tuple>
inline constexpr auto tuple_contains_v{ tuple_contains<T, Tuple>::value };
template<typename T, typename Tuple>
inline constexpr auto tuple_index_v{ tuple_index<T, Tuple>::value };
}
template<typename EventList>
class ObserverInterface;
template<typename ObserverList>
class ObserverManager;
template<typename EventList, typename ObserverList>
class EventManager;
template<typename T>
class EventHandler
{
public:
virtual void Receive(const T&) = 0;
};
template<typename ...Events>
class ObserverInterface<std::tuple<Events...>>
: public EventHandler<Events>...
{};
template<typename ...Observers>
class ObserverManager<std::tuple<Observers...>>
{
public:
template<typename T>
T& GetObserver() noexcept
{
return std::get<T>(observers_);
}
private:
std::tuple<Observers...> observers_;
};
template<typename ...Events, typename ...Observers>
class EventManager<std::tuple<Events...>, std::tuple<Observers...>>
{
public:
EventManager(ObserverManager<std::tuple<Observers...>>& observerManager)
: observerManager_{ observerManager }
{}
public:
template<typename T>
static constexpr bool isEvent{ tl::tuple_contains_v<T, std::tuple<Events...>> };
template<typename T>
static constexpr std::enable_if_t<isEvent<T>, std::size_t> eventIndex{ tl::tuple_index_v<T, std::tuple<Events...>> };
public:
template<typename T, typename ...Arguments>
std::enable_if_t<isEvent<T>> DispatchEvent(Arguments&&... arguments) noexcept
{
T event(std::forward<Arguments>(arguments)...);
util::for_each([&](auto&& observer){ observer.Receive(event); }, std::get<eventIndex<T>>(observers_));
}
private:
ObserverManager<std::tuple<Observers...>>& observerManager_;
std::tuple</* */> observers_;
};
struct EventOne
{
float value;
};
struct EventTwo
{
float value;
};
struct EventThree
{
float value;
};
class ObserverOne final
: public ObserverInterface<std::tuple<EventOne, EventTwo>>
{
public:
using Events = std::tuple<EventOne, EventTwo>;
void Receive(const EventOne& event) override
{
std::cout << "Received EventOne!\n";
}
void Receive(const EventTwo& event) override
{
std::cout << "Received EventTwo!\n";
}
};
class ObserverTwo final
: public ObserverInterface<std::tuple<EventTwo, EventThree>>
{
public:
using Events = std::tuple<EventTwo, EventThree>;
void Receive(const EventTwo& event) override
{
std::cout << "Received EventTwo!\n";
}
void Receive(const EventThree& event) override
{
std::cout << "Received EventThree!\n";
}
};
using MainEventList = std::tuple<EventOne, EventTwo, EventThree>;
using MainObserverList = std::tuple<ObserverOne, ObserverTwo>;
int main()
{
ObserverManager<MainObserverList> om;
EventManager<MainEventList, MainObserverList> em(om);
em.DispatchEvent<EventTwo>(10.f);
return 0;
}
现在事件管理器中的'observers_'元组还没有被声明,因为那是我无法弄清楚如何去做的元组。
答案 0 :(得分:1)
template<class Tag>
using type_t = typename Tag::type;
template<class T> struct tag_t{using type=T; constexpr tag_t(){}};
template<class T> constexpr tag_t<T> tag{};
template<template<class...>class Z, class Tuple>
struct fmap_tuple {};
template<template<class...>class Z, class Tuple>
using fmap_tuple_t = type_t<fmap_tuple<Z,Tuple>>;
template<template<class...>class Z, class...Ts>
struct fmap_tuple<Z, std::tuple<Ts...>>:
tag_t<std::tuple<Z<Ts>...>>
{};
template<template<class...>class Z>
struct fmapper {
template<class Tuple>
using result=fmap_tuple_t<Z, Tuple>;
};
template<class...Tuples>
using cat_tuples = decltype(std::tuple_cat( std::declval<Tuples>()... ));
template<template<class...>class Z, class Tuple, class=void>
struct filter;
template<template<class...>class Z, class Tuple>
using filter_t = type_t<filter<Z,Tuple>>;
template<template<class...>class Z>
struct filter<Z, std::tuple<>,void>:tag_t<std::tuple<>>{};
template<template<class...>class Z, class T0, class...Ts>
struct filter<Z, std::tuple<T0, Ts...>, std::enable_if_t<Z<T0>::value>>:
tag_t<
cat_tuples<
std::tuple<T0>,
filter_t<Z, std::tuple<Ts...>>
>
>
{};
template<template<class...>class Z, class T0, class...Ts>
struct filter<Z, std::tuple<T0, Ts...>, std::enable_if_t<!Z<T0>::value>>:
filter<Z, std::tuple<Ts...>>
{};
template<template<class...>class Z0, template<class...>class...Zs>
struct cat_Zs {
private:
template<class...Ts>
using Zs_result = typename cat_Zs<Zs...>::template result<Ts...>;
public:
template<class...Ts>
using result= Z0<Zs_result<Ts...>>;
};
template<template<class...>class Z0>
struct cat_Zs<Z0> {
template<class...Ts> using result=Z0<Ts...>;
};
template<class T>
struct is_T {
template<class U>
using result = std::is_same<T,U>;
};
template<template<class...>class Test>
struct everything_fails_test {
template<class Tuple>
using result = std::is_same< std::tuple<>, filter_t<Test, Tuple> >;
};
template<template<class...>class Test>
struct has_test_passer {
template<class Tuple>
using result = std::integral_constant<bool,
!everything_fails_test<Test>::template result<Tuple>::value
>;
};
template<class T>
using lacks_T = everything_fails_test< is_T<T>::template result >;
template<class T>
using contains_T = has_test_passer< is_T<T>::template result >;
template<template<class...>class Z, class Tuple>
struct make_kv;
template<template<class...>class Z, class Tuple>
using make_kv_t = type_t<make_kv<Z,Tuple>>;
template<template<class...>class Z, class...Ts>
struct make_kv<Z,std::tuple<Ts...>>:tag_t<
std::tuple< std::tuple<Ts, Z<Ts>>... >
>{};
template<class Tuple>
struct get_k;
template<class Tuple>
using get_k_t=type_t<get_k<Tuple>>;
template<class K, class V>
struct get_k<std::tuple<K,V>>:tag_t<K>{};
template<class Tuple>
struct get_v;
template<class...Tuple>
using get_v_t=type_t<get_v<Tuple...>>;
template<class K, class V>
struct get_v<std::tuple<K,V>>:tag_t<V>{};
template<class Tuple>
using step1 = make_kv_t< type_t, Tuple >;
template<class T>
using value_has_T = cat_Zs<contains_T<T>::template result,get_v_t>;
template<class Tuple, class T>
using step2 = filter_t<
value_has_T<T>::template result
,step1< Tuple >
>;
template<class Tuple, class T>
using step3 = fmap_tuple_t<
get_k_t,
step2<Tuple, T>
>;
template<class Tuple, class...Targets>
using solution_base = std::tuple<
fmap_tuple_t<
std::add_lvalue_reference_t,
step3<Tuple, Targets>
>...
>;
struct A1{};
struct A2{};
struct A3{};
template<class Tuple>
using solution = solution_base<Tuple, A1, A2, A3>;
struct T1
{
using type = std::tuple<A1, A2, A3>;
};
struct T2
{
using type = std::tuple<A1, A2>;
};
struct T3
{
using type = std::tuple<A1>;
};
using input = std::tuple<T1, T2, T3>;
using answer = std::tuple<std::tuple<T1&, T2&, T3&>, std::tuple<T1&, T2&>, std::tuple<T1&>>;
static_assert( std::is_same<answer, solution<input> >::value, "works" );
或类似的东西。
我们在这里定义了一些原语 - fmap_tuple_t
,filter_t
,fmapper
,cat_tuples
,cat_Zs
,has_test_passer
,{{1} },make_kv_t
,get_v_t
。
然后我们用这些原语构建一个类型表达式。