正如您在下面的代码中所看到的,我试图模拟一个将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屠宰。可能更容易编译它。)
答案 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 ) ;