【问题标题】:Recursive variadic template method operating on tuple对元组操作的递归可变参数模板方法
【发布时间】:2015-08-08 13:22:12
【问题描述】:

我正在尝试创建一个从提供的参数构造元组并递归“填充”它的方法。不幸的是,它会产生编译错误......这是代码:

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;
}

它不是独立的,但我已经测试了 IntersectionComponents 类并且它可以工作。 allComponentsExist 调用上的代码中断。它的模板参数可能需要以其他方式指定...

这是 IntersectionComponents 类的定义,以防万一:

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 函数返回对具有指定类型(在模板参数中)的元组中对象的引用。

这是编译器的错误列表(我完全无法理解;/):

    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ę

【问题讨论】:

  • 您提供的代码不允许有人重现您的问题,请尝试缩小您的问题陈述范围或提供MCVE
  • 啊,好吧...我做了一个独立的例子,它可以工作。它一定是其他的......对不起这个问题。修复后我会写出问题所在:S
  • 根据错误信息,您的索引似乎是std::tuple 中的一个超出范围的索引。此外,它错过了allComponentsExist 的递归结束:template&lt;typename IntersectComponents/*, typename Head*/&gt; bool allComponentsExist 的重载在哪里?
  • 嗯,你是对的。基本上我在请求不在元组中的 std::tuple 元素。关于超载,我认为我有一个很明显,所以我在这里省略了它:S

标签: c++ templates c++11 tuples variadic-templates


【解决方案1】:

解决了。好吧,在我有了“天才”的想法后,我花了 3 分钟左右的时间才查看报告的所有错误位置,而不是试图理解实际错误。而且我在错误的地方搜索了错误,因为 IDE 用红色下划线了以下行:

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

实际问题是这一行:

components.set(currentComponent);

set() 应该获得对对象的引用,但 currentComponent 是一个指针...将其更改为:

components.set(*currentComponent);

错误之墙消失了。

这行错误让我意识到这一点:

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

特别是“with ComponentType = BarComponent*”部分:S

不管怎样,抱歉问的不好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-23
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-20
    • 1970-01-01
    相关资源
    最近更新 更多