【问题标题】:Duplicate type generated from template从模板生成的重复类型
【发布时间】:2018-03-03 20:27:52
【问题描述】:

我试图将“通用”映射与事件管理器实现分开,因为我需要在其他地方使用它。但我遇到了一些对我来说很不寻常的事情。所以看起来我正在尝试生成两次(至少)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


    【解决方案1】:

    您忘记为容器提供内容:

      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;
    

    【讨论】:

    • 当你觉得自己很愚蠢的那一刻......谢谢,但问题的第二部分仍然悬而未决。这个错误是什么意思?我应该编辑以确保它清楚
    • @MathieuVanNevel 错误表示元组为空,但您尝试从中获取 std::get
    • @MathieuVanNevel 阅读static_assert 失败消息:“type not in empty type list”
    • 好吧,我的想象力在这方面太过分了 o_o 谢谢!
    【解决方案2】:

    不确定...但在我看来您忘记在EventManager 中使用T_Events...

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

    containers::TypedMap<U_ListenersArray>  m_listenersMap;
    

    我想你应该写

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

    【讨论】:

      猜你喜欢
      • 2021-07-25
      • 2017-11-27
      • 1970-01-01
      • 2011-06-27
      • 1970-01-01
      • 2014-08-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      相关资源
      最近更新 更多