C++ 创建对满足特定谓词的对象的引用元组
假设我们有以下三个结构C++ 创建对满足特定谓词的对象的引用元组,c++,c++11,c++14,template-meta-programming,c++17,C++,C++11,C++14,Template Meta Programming,C++17,假设我们有以下三个结构 struct T1 { using type = std::tuple<A1, A2, A3>; } struct T2 { using type = std::tuple<A1, A2>; } struct T3 { using type = std::tuple<A1>; } struct T1 { 使用type=std::tuple; } 结构T2 { 使用type=std::tuple; } 结构T
struct T1
{
using type = std::tuple<A1, A2, A3>;
}
struct T2
{
using type = std::tuple<A1, A2>;
}
struct T3
{
using type = std::tuple<A1>;
}
struct T1
{
使用type=std::tuple;
}
结构T2
{
使用type=std::tuple;
}
结构T3
{
使用type=std::tuple;
}
然后创建一个元组,其中包含以下类型的实例:
std::tuple<T1, T2, T3> types;
std::元组类型;
现在是棘手的部分-我如何创建这样的元组
std::tuple<std::tuple<T1&, T2&, T3&>, std::tuple<T1&, T2&>, std::tuple<T1&>>
std::tuple
在“类型”元组之外,其中
1) 。。。第一个元组包含对嵌套typedefs包含A1的所有元素的引用
2) 。。。第二个元组包含对嵌套typedefs包含A2的所有元素的引用
3) 。。。第三个元组包含对嵌套typedefs包含的所有元素的引用
编辑 我举了一个小例子来说明我正在尝试做什么,请记住这段代码还不起作用,但它应该能让您更好地理解我正在尝试做什么
#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;
}
#包括
#包括
#包括
#包括
命名空间util
{
模板
每个(函数和函数、元组和元组)的void
{
std::apply([&函数](auto&&…xs){(函数(std::forward(xs)),…);},std::forward(tuple));
}
}
名称空间tl
{
模板
结构元组包含;
模板
结构元组索引;
模板
结构元组包含
:std::bool_常数
{};
模板
结构元组索引
:std::积分常数
{};
模板
内联constexpr auto tuple_contains_v{tuple_contains::value};
模板
内联constexpr auto tuple_index_v{tuple_index::value};
}
模板
类observer接口;
模板
班级管理者;
模板
班级活动经理;
模板
类事件处理程序
{
公众:
虚空接收(常数T&)=0;
};
模板
类observer接口
:公共事件处理程序。。。
{};
模板
类观察者管理器
{
公众:
模板
T&GetObserver()不例外
{
返回std::get(观察员);
}
私人:
std::tuple;
};
模板
类事件管理器
{
公众:
事件管理器(ObserverManager和ObserverManager)
:observerManager{observerManager}
{}
公众:
模板
静态constexpr bool isEvent{tl::tuple_contains_v};
模板
静态constexpr std::enable_if_t eventIndex{tl::tuple_index_v};
公众:
模板
std::如果DispatchEvent(参数&&…参数)不例外,则启用
{
T事件(标准::转发(参数)…);
util::for_each([&](auto&&observer){observer.Receive(event);},std::get(obsers_));
}
私人:
ObserverManager和ObserverManager;
std::tuple;
};
结构事件
{
浮动值;
};
结构事件二
{
浮动值;
};
结构事件三
{
浮动值;
};
课堂观察者一个决赛
:公共观察者接口
{
公众:
使用Events=std::tuple;
无效接收(const EventOne和event)覆盖
{
std::cout模板
使用type\u t=typename标签::type;
模板结构标记{using type=t;constexpr标记{};
模板constexpr tag_t tag{};
模板
结构fmap_元组{};
模板
使用fmap\u tuple\u t=类型\u t;
模板
结构fmap_元组:
标签
{};
模板
结构模板{
模板
使用结果=fmap\u tuple\t;
};
模板
使用cat_tuples=decltype(std::tuple_cat(std::declval()…);
模板
结构过滤器;
模板
使用过滤器\u t=类型\u t;
模板
结构过滤器:tag_t{};
模板
结构过滤器:
标签<
猫元组<
std::tuple,
过滤器
>
>
{};
模板
结构过滤器>:
滤波器
{};
模板
结构cat_Zs{
私人:
模板
使用Zs_result=typename cat_Zs::template result;
公众:
模板
使用结果=Z0;
};
模板
结构cat_Zs{
模板使用结果=Z0;
};
模板
结构是{
模板
使用结果=标准::是相同的;
};
模板
结构所有内容\u未通过\u测试{
模板
使用result=std::is_same;
};
模板
结构已通过测试{
模板
使用结果=标准::积分常数;
};
模板
使用loaks_T=一切都失败了_test;
模板
使用contains_T=has_test_passer;
模板
结构制造;
模板
使用make_kv_t=类型;
模板
结构制造:标签<
std::tuple
>{};
模板
结构获取;
模板
使用get_k_t=type_t;
模板
结构get_k:tag_t{};
模板
结构获取;
模板
使用get_v_t=type_t;
模板
结构get_v:tag_t{};
模板
使用步骤1=make_kv_t;
模板
使用值_has_T=cat_Zs;
模板
使用步骤2=过滤器<
值\u具有\u T::模板结果
,步骤1<元组>
>;
模板
使用step3=fmap\u tuple\t<
得到k__t,
步骤二
>;
模板
使用solution_base=std::tuple<
fmap_tuple_t<
标准::添加左值参考值,
步骤三
>...
>;
结构A1{};
结构A2{};
结构A3{};
模板
使用溶液=溶液\基础;
结构T1
{
使用type=std::tuple
这里我们定义了一些原语--fmap\u tuple\u t
,filter\u t
,fmapper
,cat\u tuples
,cat\u Zs
,拥有测试通行证
,make\u kv\u t
,get\u v\u t
然后,我们用这些原语构建一个类型表达式。这是一个奇怪的特定请求。也是一个非常不特定的请求(tuple
转换成什么?tuple
转换成什么?tuple
?tuple
?a是如何发挥作用的?)。您尝试过什么?将std::tuple
转换为std::tuple
似乎很容易。将std::tuple
转换为std::tuple
似乎也很容易。这是一个痛苦的过程。但是,如果有一个调试过的TMP库,请将tuple
映射到tuple
,将tuple
映射到tuple
,筛选tuple
通过Pred
,将tuple
映射到tup
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" );