简体   繁体   中英

Recursive variadic template method operating on tuple

I'm trying to make a method which constructs a tuple from provided parameters, and 'fills' it recursively. Unfortunately, it yields compilation errors... This is the code:

template<typename Head, typename... Tail>
std::vector<IntersectionComponents<Head, Tail...>> intersection() {
    std::vector<IntersectionComponents<Head, Tail...>> results;

    auto& headComponents = *getAllComponents<Head>();
    for (auto& headComponent : headComponents) {
        IntersectionComponents<Head, Tail...> currentEntityRequiredComponents;
        if (allComponentsExist<IntersectionComponents<Head, Tail...>, Tail...>(headComponent.entityID, currentEntityRequiredComponents)) {
            currentEntityRequiredComponents.set(headComponent);
            results.push_back(std::move(currentEntityRequiredComponents));
        }
    }

    return results;
}

    template<typename IntersectComponents, typename Head, typename... Tail>
bool allComponentsExist(EntityID entityID, IntersectComponents& components) {
    auto currentComponent = getComponent<Head>(entityID);
    if (!currentComponent) {
        return false;
    }

    if (allComponentsExist<IntersectComponents, Tail...>(entityID, components)) {
        components.set(currentComponent);
        return true;
    }

    return false;
}

It's not self contained, but I've tested IntersectionComponents class and it works. Code breaks on allComponentsExist call. It's template parameters probably need to be specified some other way...

This is definition of IntersectionComponents class, in case it would be helpful:

template<typename... ComponentTypes>
class IntersectionComponents {
public:
    template<typename ComponentType>
    ComponentType& get() {
        return *getByType<ComponentType*>(components);
    }

private:
    std::tuple<ComponentTypes* ...> components;

    template<typename ComponentType>
    void set(ComponentType& component) {
        getByType<ComponentType*>(components) = &component;
    }

    friend class ComponentsManager;
};

getByType function returns reference to object in a tuple with the specified type(in template parameter).

Here's the error list from compiler(completely incomprehensible for me ;/):

    In file included from /usr/include/c++/5.2.0/functional:55:0,
                 from /usr/include/c++/5.2.0/memory:79,
                 from /mnt/data/dev/Active/ECS/src/3party/catch.hpp:426,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:1:
/usr/include/c++/5.2.0/tuple: In instantiation of ‘struct std::tuple_element<1ul, std::tuple<BarComponent*> >’:
/usr/include/c++/5.2.0/tuple:755:12:   required from ‘struct std::tuple_element<2ul, std::tuple<FooComponent*, BarComponent*> >’
/usr/include/c++/5.2.0/tuple:769:69:   required by substitution of ‘template<long unsigned int __i, class _Tp> using __tuple_element_t = typename std::tuple_element::type [with long unsigned int __i = 2ul; _Tp = std::tuple<FooComponent*, BarComponent*>]’
/usr/include/c++/5.2.0/tuple:844:5:   required by substitution of ‘template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(std::tuple<_Elements ...>&&) [with long unsigned int __i = 2ul; _Elements = {FooComponent*, BarComponent*}]’
/mnt/data/dev/Active/ECS/src/utils/getTupleElementByID.h:31:103:   required from ‘T& getByType(std::tuple<_Elements ...>&) [with T = BarComponent**; TupleElems = {FooComponent*, BarComponent*}]’
/mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:27:34:   required from ‘void IntersectionComponents<ComponentTypes>::set(ComponentType&) [with ComponentType = BarComponent*; ComponentTypes = {FooComponent, BarComponent}]’
/mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:148:13:   required from ‘bool ComponentsManager::allComponentsExist(EntityID, IntersectComponents&) [with IntersectComponents = IntersectionComponents<FooComponent, BarComponent>; Head = BarComponent; Tail = {}; EntityID = unsigned int]’
/mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:118:83:   required from ‘std::vector<IntersectionComponents<Head, Tail ...> > ComponentsManager::intersection() [with Head = FooComponent; Tail = {BarComponent}]’
/mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:75:64:   required from here
/usr/include/c++/5.2.0/tuple:755:12: error: invalid use of incomplete type ‘struct std::tuple_element<0ul, std::tuple<> >’
     struct tuple_element<__i, tuple<_Head, _Tail...> >
            ^
In file included from /usr/include/c++/5.2.0/algorithm:60:0,
                 from /mnt/data/dev/Active/ECS/src/3party/catch.hpp:67,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:1:
/usr/include/c++/5.2.0/utility:85:11: note: declaration of ‘struct std::tuple_element<0ul, std::tuple<> >’
     class tuple_element;
           ^
In file included from /mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:4:0,
                 from /mnt/data/dev/Active/ECS/include/../src/core/engine.h:4,
                 from /mnt/data/dev/Active/ECS/./include/ecs/ecs.h:3,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:2:
/mnt/data/dev/Active/ECS/src/utils/getTupleElementByID.h: In instantiation of ‘T& getByType(std::tuple<_Elements ...>&) [with T = BarComponent**; TupleElems = {FooComponent*, BarComponent*}]’:
/mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:27:34:   required from ‘void IntersectionComponents<ComponentTypes>::set(ComponentType&) [with ComponentType = BarComponent*; ComponentTypes = {FooComponent, BarComponent}]’
/mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:148:13:   required from ‘bool ComponentsManager::allComponentsExist(EntityID, IntersectComponents&) [with IntersectComponents = IntersectionComponents<FooComponent, BarComponent>; Head = BarComponent; Tail = {}; EntityID = unsigned int]’
/mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:118:83:   required from ‘std::vector<IntersectionComponents<Head, Tail ...> > ComponentsManager::intersection() [with Head = FooComponent; Tail = {BarComponent}]’
/mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:75:64:   required from here
/mnt/data/dev/Active/ECS/src/utils/getTupleElementByID.h:31:103: error: no matching function for call to ‘get(std::tuple<FooComponent*, BarComponent*>&)’
     return std::get<detail::get_number_of_element_from_tuple_by_type_impl<T, 0, TupleElems...>::value>(t);
                                                                                                       ^
In file included from /usr/include/c++/5.2.0/algorithm:60:0,
                 from /mnt/data/dev/Active/ECS/src/3party/catch.hpp:67,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:1:
/usr/include/c++/5.2.0/utility:147:5: note: candidate: template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)
     get(std::pair<_Tp1, _Tp2>& __in) noexcept
     ^
/usr/include/c++/5.2.0/utility:147:5: note:   template argument deduction/substitution failed:
In file included from /mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:4:0,
                 from /mnt/data/dev/Active/ECS/include/../src/core/engine.h:4,
                 from /mnt/data/dev/Active/ECS/./include/ecs/ecs.h:3,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:2:
/mnt/data/dev/Active/ECS/src/utils/getTupleElementByID.h:31:103: note:   ‘std::tuple<FooComponent*, BarComponent*>’ is not derived from ‘std::pair<_Tp1, _Tp2>’
     return std::get<detail::get_number_of_element_from_tuple_by_type_impl<T, 0, TupleElems...>::value>(t);
                                                                                                       ^
In file included from /usr/include/c++/5.2.0/algorithm:60:0,
                 from /mnt/data/dev/Active/ECS/src/3party/catch.hpp:67,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:1:
/usr/include/c++/5.2.0/utility:152:5: note: candidate: template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(std::pair<_Tp1, _Tp2>&&)
     get(std::pair<_Tp1, _Tp2>&& __in) noexcept
     ^
/usr/include/c++/5.2.0/utility:152:5: note:   template argument deduction/substitution failed:
In file included from /mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:4:0,
                 from /mnt/data/dev/Active/ECS/include/../src/core/engine.h:4,
                 from /mnt/data/dev/Active/ECS/./include/ecs/ecs.h:3,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:2:
/mnt/data/dev/Active/ECS/src/utils/getTupleElementByID.h:31:103: note:   ‘std::tuple<FooComponent*, BarComponent*>’ is not derived from ‘std::pair<_Tp1, _Tp2>’
     return std::get<detail::get_number_of_element_from_tuple_by_type_impl<T, 0, TupleElems...>::value>(t);
                                                                                                       ^
In file included from /usr/include/c++/5.2.0/algorithm:60:0,
                 from /mnt/data/dev/Active/ECS/src/3party/catch.hpp:67,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:1:
/usr/include/c++/5.2.0/utility:157:5: note: candidate: template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)
     get(const std::pair<_Tp1, _Tp2>& __in) noexcept
     ^
/usr/include/c++/5.2.0/utility:157:5: note:   template argument deduction/substitution failed:
In file included from /mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:4:0,
                 from /mnt/data/dev/Active/ECS/include/../src/core/engine.h:4,
                 from /mnt/data/dev/Active/ECS/./include/ecs/ecs.h:3,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:2:
/mnt/data/dev/Active/ECS/src/utils/getTupleElementByID.h:31:103: note:   ‘std::tuple<FooComponent*, BarComponent*>’ is not derived from ‘const std::pair<_Tp1, _Tp2>’
     return std::get<detail::get_number_of_element_from_tuple_by_type_impl<T, 0, TupleElems...>::value>(t);
                                                                                                       ^
In file included from /usr/include/c++/5.2.0/algorithm:60:0,
                 from /mnt/data/dev/Active/ECS/src/3party/catch.hpp:67,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:1:
/usr/include/c++/5.2.0/utility:166:5: note: candidate: template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_T1, _T2>&)
     get(pair<_Tp, _Up>& __p) noexcept
     ^
/usr/include/c++/5.2.0/utility:166:5: note:   template argument deduction/substitution failed:
/usr/include/c++/5.2.0/utility:171:5: note: candidate: template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_T1, _T2>&)
     get(const pair<_Tp, _Up>& __p) noexcept
     ^
/usr/include/c++/5.2.0/utility:171:5: note:   template argument deduction/substitution failed:
/usr/include/c++/5.2.0/utility:176:5: note: candidate: template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_T1, _T2>&&)
     get(pair<_Tp, _Up>&& __p) noexcept
     ^
/usr/include/c++/5.2.0/utility:176:5: note:   template argument deduction/substitution failed:
/usr/include/c++/5.2.0/utility:181:5: note: candidate: template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_Up, _Tp>&)
     get(pair<_Up, _Tp>& __p) noexcept
     ^
/usr/include/c++/5.2.0/utility:181:5: note:   template argument deduction/substitution failed:
/usr/include/c++/5.2.0/utility:186:5: note: candidate: template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_Up, _Tp>&)
     get(const pair<_Up, _Tp>& __p) noexcept
     ^
/usr/include/c++/5.2.0/utility:186:5: note:   template argument deduction/substitution failed:
/usr/include/c++/5.2.0/utility:191:5: note: candidate: template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_Up, _Tp>&&)
     get(pair<_Up, _Tp>&& __p) noexcept
     ^
/usr/include/c++/5.2.0/utility:191:5: note:   template argument deduction/substitution failed:
In file included from /usr/include/c++/5.2.0/tuple:39:0,
                 from /usr/include/c++/5.2.0/functional:55,
                 from /usr/include/c++/5.2.0/memory:79,
                 from /mnt/data/dev/Active/ECS/src/3party/catch.hpp:426,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:1:
/usr/include/c++/5.2.0/array:280:5: note: candidate: template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr _Tp& std::get(std::array<_Tp, _Nm>&)
     get(array<_Tp, _Nm>& __arr) noexcept
     ^
/usr/include/c++/5.2.0/array:280:5: note:   template argument deduction/substitution failed:
In file included from /mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:4:0,
                 from /mnt/data/dev/Active/ECS/include/../src/core/engine.h:4,
                 from /mnt/data/dev/Active/ECS/./include/ecs/ecs.h:3,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:2:
/mnt/data/dev/Active/ECS/src/utils/getTupleElementByID.h:31:103: note:   ‘std::tuple<FooComponent*, BarComponent*>’ is not derived from ‘std::array<_Tp, _Nm>’
     return std::get<detail::get_number_of_element_from_tuple_by_type_impl<T, 0, TupleElems...>::value>(t);
                                                                                                       ^
In file included from /usr/include/c++/5.2.0/tuple:39:0,
                 from /usr/include/c++/5.2.0/functional:55,
                 from /usr/include/c++/5.2.0/memory:79,
                 from /mnt/data/dev/Active/ECS/src/3party/catch.hpp:426,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:1:
/usr/include/c++/5.2.0/array:289:5: note: candidate: template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr _Tp&& std::get(std::array<_Tp, _Nm>&&)
     get(array<_Tp, _Nm>&& __arr) noexcept
     ^
/usr/include/c++/5.2.0/array:289:5: note:   template argument deduction/substitution failed:
In file included from /mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:4:0,
                 from /mnt/data/dev/Active/ECS/include/../src/core/engine.h:4,
                 from /mnt/data/dev/Active/ECS/./include/ecs/ecs.h:3,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:2:
/mnt/data/dev/Active/ECS/src/utils/getTupleElementByID.h:31:103: note:   ‘std::tuple<FooComponent*, BarComponent*>’ is not derived from ‘std::array<_Tp, _Nm>’
     return std::get<detail::get_number_of_element_from_tuple_by_type_impl<T, 0, TupleElems...>::value>(t);
                                                                                                       ^
In file included from /usr/include/c++/5.2.0/tuple:39:0,
                 from /usr/include/c++/5.2.0/functional:55,
                 from /usr/include/c++/5.2.0/memory:79,
                 from /mnt/data/dev/Active/ECS/src/3party/catch.hpp:426,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:1:
/usr/include/c++/5.2.0/array:297:5: note: candidate: template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr const _Tp& std::get(const std::array<_Tp, _Nm>&)
     get(const array<_Tp, _Nm>& __arr) noexcept
     ^
/usr/include/c++/5.2.0/array:297:5: note:   template argument deduction/substitution failed:
In file included from /mnt/data/dev/Active/ECS/include/../src/core/componentsManager.h:4:0,
                 from /mnt/data/dev/Active/ECS/include/../src/core/engine.h:4,
                 from /mnt/data/dev/Active/ECS/./include/ecs/ecs.h:3,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:2:
/mnt/data/dev/Active/ECS/src/utils/getTupleElementByID.h:31:103: note:   ‘std::tuple<FooComponent*, BarComponent*>’ is not derived from ‘const std::array<_Tp, _Nm>’
     return std::get<detail::get_number_of_element_from_tuple_by_type_impl<T, 0, TupleElems...>::value>(t);
                                                                                                       ^
In file included from /usr/include/c++/5.2.0/functional:55:0,
                 from /usr/include/c++/5.2.0/memory:79,
                 from /mnt/data/dev/Active/ECS/src/3party/catch.hpp:426,
                 from /mnt/data/dev/Active/ECS/tests/core/componentsManagerTests.cpp:1:
/usr/include/c++/5.2.0/tuple:832:5: note: candidate: template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(std::tuple<_Elements ...>&)
     get(tuple<_Elements...>& __t) noexcept
     ^
/usr/include/c++/5.2.0/tuple:832:5: note:   template argument deduction/substitution failed:
/usr/include/c++/5.2.0/tuple:838:5: note: candidate: template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(const std::tuple<_Elements ...>&)
     get(const tuple<_Elements...>& __t) noexcept
     ^
/usr/include/c++/5.2.0/tuple:838:5: note:   template argument deduction/substitution failed:
/usr/include/c++/5.2.0/tuple:844:5: note: candidate: template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(std::tuple<_Elements ...>&&)
     get(tuple<_Elements...>&& __t) noexcept
     ^
/usr/include/c++/5.2.0/tuple:844:5: note:   substitution of deduced template arguments resulted in errors seen above
/usr/include/c++/5.2.0/tuple:867:5: note: candidate: template<class _Tp, class ... _Types> constexpr _Tp& std::get(std::tuple<_Elements ...>&)
     get(tuple<_Types...>& __t) noexcept
     ^
/usr/include/c++/5.2.0/tuple:867:5: note:   template argument deduction/substitution failed:
/usr/include/c++/5.2.0/tuple:873:5: note: candidate: template<class _Tp, class ... _Types> constexpr _Tp&& std::get(std::tuple<_Elements ...>&&)
     get(tuple<_Types...>&& __t) noexcept
     ^
/usr/include/c++/5.2.0/tuple:873:5: note:   template argument deduction/substitution failed:
/usr/include/c++/5.2.0/tuple:879:5: note: candidate: template<class _Tp, class ... _Types> constexpr const _Tp& std::get(const std::tuple<_Elements ...>&)
     get(const tuple<_Types...>& __t) noexcept
     ^
/usr/include/c++/5.2.0/tuple:879:5: note:   template argument deduction/substitution failed:
CMakeFiles/tests.dir/build.make:77: polecenia dla obiektu 'CMakeFiles/tests.dir/tests/core/componentsManagerTests.cpp.o' nie powiodły się

Solved it. Well, it took 3 minutes or so after I've got 'genius' idea to just look at all error locations reported instead of trying to comprehend actual errors. And I've searched for error in the wrong place, due to IDE which underlined following line in red:

allComponentsExist<IntersectionComponents<Head, Tail...>, Tail...>(headComponent.entityID, currentEntityRequiredComponents));

Actual problem was this line:

components.set(currentComponent);

set() should get reference to object, but currentComponent was a pointer... changed it to:

components.set(*currentComponent);

And wall of errors is gone.

This line of errors made me realize this:

...componentsManager.h:27:34:   required from ‘void IntersectionComponents<ComponentTypes>::set(ComponentType&) [with ComponentType = BarComponent*; ComponentTypes = {FooComponent, BarComponent}]’

Specifically "with ComponentType = BarComponent*" part :S

Anyway, sorry for bad question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM