std :: tuple_element<> ::类型解析问题

时间:2014-07-08 20:08:43

标签: c++ templates

正如您在下面的代码中所看到的,我试图模拟一个将std::tuple<>消息提供给工厂的回调结构。我的问题是看起来编译器没有减少&#34;返回类型&#34; (例如)std::tuple_element< 2, MessageOne, MessageTwo, MessageTen >只是MessageTwo - 这使得链接混乱。见下文。

#include <map>
#include <tuple>

//----------------------------------------------------------------------
//
class MessageBase
{
  public:
    MessageBase( const int _id ) : m_id( _id ) { }
    virtual int getMessageID() const = 0;

  private:
    const int m_id;
};

#define MESSAGE( NAME, VAL ) \
  class Message##NAME : public MessageBase { \
    public: \
      Message##NAME() : MessageBase( VAL ) { } \
      virtual int getMessageID() const { return ( VAL ); } \
  }

  MESSAGE( One, 1 );
  MESSAGE( Two, 2 );
  MESSAGE( Ten, 10 );

class StaticMessageHandlerInterface
{
  public:

    virtual void processMsg( const MessageOne& ) { }
    virtual void processMsg( const MessageTwo& ) { }
    virtual void processMsg( const MessageTen& ) { }
};


//----------------------------------------------------------------------
//
class MessageCallbackInterface
{
  public:
    virtual void receiveMsg( const MessageBase* ) = 0;

};

template< class MessageT, class HandlerT >
class MessageCallbackHandler : public MessageCallbackInterface
{
  public:
    MessageCallbackHandler( HandlerT& _handler )
      : r_handler( _handler )
    { }

    void receiveMsg( const MessageBase* _msg )
    {
      const MessageT* msg( ( const MessageT* )(_msg) );
      r_handler.processMsg( *msg );
    }

  private:
    HandlerT& r_handler;

}; // MessageCallbackHandler


//----------------------------------------------------------------------
//
template< typename TupleT >
class MessageFactory
{
  public:
    MessageFactory()
      : p_handler( nullptr )
    {
      init( TupleT() );
    }

  private:

    StaticMessageHandlerInterface* p_handler;

    typedef std::map< int, MessageCallbackInterface* > MessageCallbackMap;
    MessageCallbackMap m_callbackMap;

    template< std::size_t I = 0, typename ... T >
    inline typename std::enable_if< I < sizeof ... (T), void >::type
    init( const std::tuple< T... >& t )
    {
      const auto& msg( std::get<I>( t ) );

      m_callbackMap[ msg.getMessageID() ] =
        new MessageCallbackHandler <
          std::tuple_element< I, std::tuple< T ... > >,
          StaticMessageHandlerInterface
         > ( *p_handler ) ;

      init< I + 1, T... >( t );
    }

    template< std::size_t I = 0, typename ... T >
    inline typename std::enable_if< I == sizeof... (T), void >::type
    init( const std::tuple< T... >& ) { }

};

//----------------------------------------------------------------------
//
int
main( const int, const char** )
{
  typedef std::tuple< MessageOne, MessageTwo, MessageTen > Foople;

  typedef MessageFactory< Foople > FoopleFactory;
  FoopleFactory factory;
}
从那以后,GCC抱怨......

  

test.C:实例化&#39; void MessageCallbackHandler(MessageT,   HandlerT):: receiveMsg(const MessageBase *)[with MessageT =   std :: tuple_element(2u,std :: tuple(MessageOne,MessageTwo,MessageTen)   ); HandlerT = StaticMessageHandlerInterface]&#39 ;:test.C:143:5:
  从这里需要test.C:83:11:错误:没有匹配的呼叫功能   to&#39; StaticMessageHandlerInterface :: processMsg(const   std :: tuple_element(2u,std :: tuple(MessageOne,MessageTwo,MessageTen)   )及)&#39;              r_handler.processMsg(* msg);              ^ test.C:83:11:注意:候选者是:test.C:57:22:注意:virtual void StaticMessageHandlerInterface :: processMsg(const   MessageOne的&安培)            virtual void processMsg(const MessageOne&amp;){}                         ^ test.C:57:22:注意:没有已知的转换参数1来自&#39; const std :: tuple_element(2u,std :: tuple(MessageOne,   MessageTwo,MessageTen))&#39; to&#39; const MessageOne&amp;&#39; test.C:58:22:注意:   virtual void StaticMessageHandlerInterface :: processMsg(const   MessageTwo&安培)            virtual void processMsg(const MessageTwo&amp;){}                         ^ test.C:58:22:注意:没有已知的转换参数1来自&#39; const std :: tuple_element(2u,std :: tuple(MessageOne,   MessageTwo,MessageTen))&#39; to&#39; const MessageTwo&amp;&#39; test.C:59:22:注意:   virtual void StaticMessageHandlerInterface :: processMsg(const   MessageTen&安培)            virtual void processMsg(const MessageTen&amp;){}                         ^ test.C:60:22:注意:没有已知的转换参数1来自&#39; const std :: tuple_element(2u,std :: tuple(MessageOne,   MessageTwo,MessageTen))&#39;到&#39; const MessageTen&amp;&#39;

(对不起Markdown屠宰。可能更容易编译它。)

1 个答案:

答案 0 :(得分:1)

您需要访问inner typedef以获取实际的元素类型。现在你正在传递std::tuple_element类型。

  m_callbackMap[ msg.getMessageID() ] =
    new MessageCallbackHandler <
      typename std::tuple_element< I, std::tuple< T ... > >::type,
      StaticMessageHandlerInterface
     > ( *p_handler ) ;