将运行时研究更改为编译时研究 我试图在C++中实现一个通用的ECS库,以供学习。我想了很多方法来实现这些东西,但我总是遇到问题。如果你能帮我解决这个问题:

将运行时研究更改为编译时研究 我试图在C++中实现一个通用的ECS库,以供学习。我想了很多方法来实现这些东西,但我总是遇到问题。如果你能帮我解决这个问题:,c++,metaprogramming,boost-hana,C++,Metaprogramming,Boost Hana,假设我有一个constepr-hana::tuple的hana::type_c组件,类似于: struct C1 {}; struct C2 {}; struct C3 {}; constexpr auto components = hana::to_tuple(hana::tuple_t<C1, C2, C3>); 我想将每个组件或每个组件组与其存储类型链接起来。所以简单的方法就是这样做: constexpr auto component_storage = hana::mak

假设我有一个
constepr-hana::tuple
hana::type_c
组件,类似于:

struct C1 {};
struct C2 {};
struct C3 {};

constexpr auto components = hana::to_tuple(hana::tuple_t<C1, C2, C3>);
我想将每个组件或每个组件组与其
存储类型链接起来。所以简单的方法就是这样做:

constexpr auto component_storage = hana::make_tuple(
hana::make_pair(hana::to_tuple(hana::tuple_t<C1, C2>), type_c<Storage>),
hana::make_pair(hana::to_tuple(hana::tuple_t<C3>), type_c<Storage>)
);
至少是这样的:

constexpr auto components = hana::to_tuple(hana::tuple_t<C1, C2, C3>);
constexpr auto storage = hana::to_tuple(hana::tuple_t<Storage, Storage>);
constexpr auto index = hana::make_tuple(
hana::make_pair(hana::to_tuple(hana::tuple_t<C1>, 0),
hana::make_pair(hana::to_tuple(hana::tuple_t<C2, C3>, 1)
);
constepr auto components=hana::to_tuple(hana::tuple_t);
constexpr auto storage=hana::to_tuple(hana::tuple_t);
constexpr auto index=hana::make_tuple(
hana::make_pair(hana::to_tuple(hana::tuple_t,0),
hana::make_pair(hana::to_tuple(hana::tuple_t,1)
);

像这样,我应该能够在编译时找到索引,并在运行时访问正确的元素。但是我对元编程是新手,所以我想有人可以做得更好。

首先,不需要使用
到tuple(tuple _t)
;你可以只使用
tuple _t
。现在,我想你真正想做的是什么(因为您似乎需要运行时存储,这很有意义)是:

//“映射”一组类型到某一类型的存储器
使用StorageMap=hana::tuple<
哈娜:一对,
哈娜:对
>;
//包含运行时存储(以及类型之间的自由映射)的实际对象
存储地图;
现在,您可以像这样实现
getStorage()
函数:

template <typename Component>
decltype(auto) getStorage() {
  auto found = index_if(map, [](auto const& pair) {
    return hana::contains(hana::first(pair), hana::type<Component>{});
  });
  return hana::second(hana::at(map, found));
}
模板
decltype(自动)getStorage(){
自动查找=索引_if(映射,[](自动常量和对){
返回hana::contains(hana::first(pair),hana::type{});
});
返回hana::second(hana::at(map,find));
}

其中,
index\u if
是函数的一个简单变体,它可以处理任意谓词而不是特定元素。当我有空闲时间时,此功能将添加到Hana中(请参阅)。

首先,无需使用
to\u tuple(tuple\t)
;您只需使用
tuple\t
。现在,我认为您真正想要做的是(因为您似乎需要运行时存储,这很有意义):

//“映射”一组类型到某一类型的存储器
使用StorageMap=hana::tuple<
哈娜:一对,
哈娜:对
>;
//包含运行时存储(以及类型之间的自由映射)的实际对象
存储地图;
现在,您可以像这样实现
getStorage()
函数:

template <typename Component>
decltype(auto) getStorage() {
  auto found = index_if(map, [](auto const& pair) {
    return hana::contains(hana::first(pair), hana::type<Component>{});
  });
  return hana::second(hana::at(map, found));
}
模板
decltype(自动)getStorage(){
自动查找=索引_if(映射,[](自动常量和对){
返回hana::contains(hana::first(pair),hana::type{});
});
返回hana::second(hana::at(map,find));
}

其中,
index\u if
是函数的一个简单变体,它可以处理任意谓词而不是特定元素。当我有空闲时间时,此功能将添加到Hana中(请参阅).

看起来您正在尝试创建一个可以使用不同键查找单个实例的映射。下面是我编写的一个旧实现的片段。我对它进行了一些修改,但它应该传达了这个想法

namespace detail {
    // extractKeys - returns pairs of each element and itself
    struct extract_keys_fn
    {
        template<typename TypesType>
        constexpr auto operator()(TypesType s) const {
            return decltype(hana::unpack(typename TypesType::type{},
                hana::make_tuple
                ^hana::on^
                hana::reverse_partial(hana::make_pair, s)
            )){};
        }
    };
    constexpr extract_keys_fn extract_keys{};
}//detail

template<typename ...Pair>
struct multi_map
{
    // the keys must be `type<tuple<path...>>`
    using Storage = decltype(hana::make_map(std::declval<Pair>()...));

    // each key is a hana::tuple which contain the keys we
    // want to use to lookup an element
    using Lookup = decltype(hana::unpack(
        hana::flatten(hana::unpack(hana::keys(std::declval<Storage>()),
            hana::make_tuple ^hana::on^ detail::extract_keys)),
        hana::make_map
    ));

    constexpr multi_map()
        : storage()
    { }

    constexpr multi_map(Pair&&... p)
        : storage(hana::make_map(std::forward<Pair>(p)...))
    { }

    constexpr multi_map(Pair const&... p)
        : storage(hana::make_map(p...))
    { }

    constexpr multi_map(Pair&... p)
        : storage(hana::make_map(p...))
    { }

    template<typename T>
    constexpr decltype(auto) operator[](T t) const&
    {
        return hana::at_key(storage, hana::at_key(Lookup{}, t));
    }

    template<typename T>
    constexpr decltype(auto) operator[](T t) &
    {
        return hana::at_key(storage, hana::at_key(Lookup{}, t));
    }

    template<typename T>
    constexpr decltype(auto) operator[](T t) &&
    {
        return hana::at_key(storage, hana::at_key(Lookup{}, t));
    }

    Storage storage;
};
名称空间详细信息{
//extractKeys-返回每个元素及其自身的对
结构提取\u键\u fn
{
模板
constexpr自动运算符()(TypesType s)const{
返回decltype(hana::unpack(typename TypesType::type{}),
hana::make_tuple
^哈娜:在^
hana::反向_部分(hana::生成_对,s)
)){};
}
};
constexpr extract_keys_fn extract_keys{};
}//细部
模板
结构多重映射
{
//钥匙必须是`类型`
使用Storage=decltype(hana::make_-map(std::declval()…);
//每个键都是一个hana::元组,其中包含我们需要的键
//要用于查找元素吗
使用Lookup=decltype(hana::解包(
hana::展平(hana::解包(hana::键(std::declval()),
hana::生成\u元组^hana::在^detail::extract\u keys)上,
hana::制作地图
));
constexpr multi_map()
:存储()
{ }
constexpr多重映射(成对和…p)
:存储(hana::生成映射(std::转发(p)…)
{ }
constexpr多重映射(成对const&…p)
:存储(hana::制作地图(第页)
{ }
constexpr多重映射(对和…p)
:存储(hana::制作地图(第页)
{ }
模板
constexpr decltype(自动)运算符[](T)const&
{
返回hana::at_键(存储,hana::at_键(查找{},t));
}
模板
constexpr decltype(自动)运算符[](T)&
{
返回hana::at_键(存储,hana::at_键(查找{},t));
}
模板
constexpr decltype(自动)运算符[](T)&&
{
返回hana::at_键(存储,hana::at_键(查找{},t));
}
储存;
};

上面发生的基本情况是
storage
是一个
hana::map
包含您需要引用的实例。然后
Lookup
是一个
hana::map
,它将每个键指向
storage
中使用的键(它是指向它的所有键的元组)。它基本上只是一个映射到映射的映射,但使用它,您可以使用任意一个键获取对单个实例的引用。

看起来您正在尝试创建一个映射,该映射可以使用不同的键查找单个实例。下面是我编写的一个旧实现的片段。我对其进行了一些修改,但它应该传达了这个想法

namespace detail {
    // extractKeys - returns pairs of each element and itself
    struct extract_keys_fn
    {
        template<typename TypesType>
        constexpr auto operator()(TypesType s) const {
            return decltype(hana::unpack(typename TypesType::type{},
                hana::make_tuple
                ^hana::on^
                hana::reverse_partial(hana::make_pair, s)
            )){};
        }
    };
    constexpr extract_keys_fn extract_keys{};
}//detail

template<typename ...Pair>
struct multi_map
{
    // the keys must be `type<tuple<path...>>`
    using Storage = decltype(hana::make_map(std::declval<Pair>()...));

    // each key is a hana::tuple which contain the keys we
    // want to use to lookup an element
    using Lookup = decltype(hana::unpack(
        hana::flatten(hana::unpack(hana::keys(std::declval<Storage>()),
            hana::make_tuple ^hana::on^ detail::extract_keys)),
        hana::make_map
    ));

    constexpr multi_map()
        : storage()
    { }

    constexpr multi_map(Pair&&... p)
        : storage(hana::make_map(std::forward<Pair>(p)...))
    { }

    constexpr multi_map(Pair const&... p)
        : storage(hana::make_map(p...))
    { }

    constexpr multi_map(Pair&... p)
        : storage(hana::make_map(p...))
    { }

    template<typename T>
    constexpr decltype(auto) operator[](T t) const&
    {
        return hana::at_key(storage, hana::at_key(Lookup{}, t));
    }

    template<typename T>
    constexpr decltype(auto) operator[](T t) &
    {
        return hana::at_key(storage, hana::at_key(Lookup{}, t));
    }

    template<typename T>
    constexpr decltype(auto) operator[](T t) &&
    {
        return hana::at_key(storage, hana::at_key(Lookup{}, t));
    }

    Storage storage;
};
名称空间详细信息{
//extractKeys-返回每个元素及其自身的对
结构提取\u键\u fn
{
模板
constexpr自动运算符()(TypesType s)const{
返回decltype(hana::unpack(typename TypesType::type{}),
hana::make_tuple
^哈娜:在^
hana::反向_部分(hana::生成_对,s)
)){};
}
};
constexpr extract_keys_fn extract_keys{};
}//细部
临时雇员
namespace detail {
    // extractKeys - returns pairs of each element and itself
    struct extract_keys_fn
    {
        template<typename TypesType>
        constexpr auto operator()(TypesType s) const {
            return decltype(hana::unpack(typename TypesType::type{},
                hana::make_tuple
                ^hana::on^
                hana::reverse_partial(hana::make_pair, s)
            )){};
        }
    };
    constexpr extract_keys_fn extract_keys{};
}//detail

template<typename ...Pair>
struct multi_map
{
    // the keys must be `type<tuple<path...>>`
    using Storage = decltype(hana::make_map(std::declval<Pair>()...));

    // each key is a hana::tuple which contain the keys we
    // want to use to lookup an element
    using Lookup = decltype(hana::unpack(
        hana::flatten(hana::unpack(hana::keys(std::declval<Storage>()),
            hana::make_tuple ^hana::on^ detail::extract_keys)),
        hana::make_map
    ));

    constexpr multi_map()
        : storage()
    { }

    constexpr multi_map(Pair&&... p)
        : storage(hana::make_map(std::forward<Pair>(p)...))
    { }

    constexpr multi_map(Pair const&... p)
        : storage(hana::make_map(p...))
    { }

    constexpr multi_map(Pair&... p)
        : storage(hana::make_map(p...))
    { }

    template<typename T>
    constexpr decltype(auto) operator[](T t) const&
    {
        return hana::at_key(storage, hana::at_key(Lookup{}, t));
    }

    template<typename T>
    constexpr decltype(auto) operator[](T t) &
    {
        return hana::at_key(storage, hana::at_key(Lookup{}, t));
    }

    template<typename T>
    constexpr decltype(auto) operator[](T t) &&
    {
        return hana::at_key(storage, hana::at_key(Lookup{}, t));
    }

    Storage storage;
};