从模板生成的重复类型

问题描述 投票:1回答:2

我试图将“通用”映射与事件管理器实现分开,因为我需要在其他地方使用它。但是我遇到了一些非常不寻常的事情。所以我似乎想要生成两次(至少)GetValue函数。

#include <tuple>
#include <utility>
#include <vector>
#include <functional>

namespace meta {

    template < typename T >
    struct CType { using type = T; };
}

namespace  containers {

    template < template < typename T > class T_Storage,
               typename... T_Keys >

        class TypedMap {

            template < typename T_Key >
            using U_Pair = decltype(
                std::make_pair(
                    meta::CType<T_Key>{},
                    T_Storage<T_Key>{}
                ));
            using U_Map = decltype(
                std::make_tuple(
                    U_Pair<T_Keys>{}
                    ...));

            public:
              U_Map m_map;

            //-----------------------------------------
            //! Functions
            public:
            //!
            //! @fn GetValue
            //! @brief Acess to map[key]
            //! @param type is the key used to find the data
            //! @return map[key] reference
            //!
            template < typename T_Key >
            constexpr decltype(auto) GetPair() {

                return std::get<U_Pair<T_Key>>(m_map);
            }

            template < typename T_Key >
            decltype(auto)  GetValue() {

                return std::get<1>(GetPair<T_Key>());
            }
        };
}


  //!
  //! @class EventManager
  //!
  template < typename ... T_Events >
  class  EventManager {

    template < typename T_Event >
    using U_EventCallback = std::function<void(T_Event)>;
    template < typename T_Event >
    using U_ListenersArray = std::vector<U_EventCallback<T_Event>>;

    private:
      containers::TypedMap<U_ListenersArray>  m_listenersMap;

    public:
      EventManager() = default;
      ~EventManager() = default;

    public:
      template < typename T_Event >
      decltype(auto)  GetListeners() {

        return m_listenersMap.template GetValue<T_Event>();
      }
  };


struct event1 {};
struct event2 {};

using U_EventManager = EventManager<event1,event2>;

int main() { 

    U_EventManager test;
    auto result = test.GetListeners<event1>();
}

Wandbox

更新:

所以错误是由于一个错字而产生的...但是我仍然想知道这个错误是如何发生的,以便下次能够理解它。

In file included from prog.cc:1: /opt/wandbox/clang-head/include/c++/v1/tuple:1018:5: error: static_assert failed due to requirement '!is_same<pair<CType<event1>, vector<function<void (event1)>, allocator<function<void (event1)> > >
>, pair<CType<event1>, vector<function<void (event1)>, allocator<function<void (event1)> > > > >::value' "type not in empty type list"
    static_assert(!is_same<_T1, _T1>::value, "type not in empty type list");
    ^             ~~~~~~~~~~~~~~~~~~~~~~~~~ /opt/wandbox/clang-head/include/c++/v1/tuple:1025:14: note: in instantiation of template class 'std::__1::__find_detail::__find_exactly_one_checked<std::__1::pair<meta::CType<event1>, std::__1::vector<std::__1::function<void (event1)>, std::__1::allocator<std::__1::function<void (event1)> > > >>' requested here
    : public __find_detail::__find_exactly_one_checked<_T1, _Args...> {
             ^ /opt/wandbox/clang-head/include/c++/v1/tuple:1032:23: note: in instantiation of template class 'std::__1::__find_exactly_one_t<std::__1::pair<meta::CType<event1>, std::__1::vector<std::__1::function<void (event1)>, std::__1::allocator<std::__1::function<void (event1)> > > >>' requested here
    return _VSTD::get<__find_exactly_one_t<_T1, _Args...>::value>(__tup);
                      ^ prog.cc:45:29: note: in instantiation of function template specialization 'std::__1::get<std::__1::pair<meta::CType<event1>, std::__1::vector<std::__1::function<void (event1)>, std::__1::allocator<std::__1::function<void (event1)> > > >>' requested here
                return std::get<U_Pair<T_Key>>(m_map);
                            ^ prog.cc:51:36: note: in instantiation of function template specialization 'containers::TypedMap<U_ListenersArray>::GetPair<event1>' requested here
                return std::get<1>(GetPair<T_Key>());
                                   ^ prog.cc:79:40: note: in instantiation of function template specialization 'containers::TypedMap<U_ListenersArray>::GetValue<event1>' requested here
        return m_listenersMap.template GetValue<T_Event>();
                                       ^ prog.cc:92:24: note: in instantiation of function template specialization 'EventManager<event1, event2>::GetListeners<event1>' requested here
    auto result = test.GetListeners<event1>();
                       ^ 1 error generated.
c++ templates c++14 variadic-templates template-meta-programming
2个回答
2
投票

您忘了为容器提供内容:

  template < typename ... T_Events >
  class  EventManager {
  /* ... */
    private:
      containers::TypedMap<U_ListenersArray>  m_listenersMap; // <-- this line, you forgot the type list.
   /* ... */
  };

标记的行应该是:

  containers::TypedMap<U_ListenersArray, T_Events...>  m_listenersMap;

1
投票

不确定......但在我看来你忘了在T_Events...使用EventManager

我的意思是......而不是

containers::TypedMap<U_ListenersArray>  m_listenersMap;

我想,你应该写一下

containers::TypedMap<U_ListenersArray, T_Events...>  m_listenersMap;
© www.soinside.com 2019 - 2024. All rights reserved.