这对我没有意义。 GCC抱怨main()
到processMsg()
下面的调用不明确,即使所有模板创建的processMsg()
调用都被报告为候选人。我曾尝试以三种不同的方式实现这种可变参数模板原型,并且它们都回到同样的模糊请求问题。当我将模板实现分解为不同的情况时,我确实接近了,但是我可以编译器只能解析元组中的第一个查找。
我贴了一个小例子。我确定我错过了一些简单的事情......
#include <tuple>
//----------------------------------------------------------------------
//
class MessageBase
{
public:
MessageBase( const int _id ) : m_id( _id ) {}
virtual int getMessageID() const { return( m_id ); }
private:
const int m_id;
};
#define MESSAGE( NAME, VAL ) \
class Message##NAME : public MessageBase { \
public: \
Message##NAME() : MessageBase( VAL ) { } \
};
MESSAGE( One, 1 );
MESSAGE( Two, 2 );
MESSAGE( Ten, 10 );
//----------------------------------------------------------------------
//
template< typename T >
struct MyMessageInterface {
virtual void processMsg( const T& t ) { }
};
template< typename... T >
struct MyMessageHandler : public MyMessageInterface< T >...
{};
template< typename... T >
struct MyMessageHandler< std::tuple< T... > >
: public MyMessageInterface< T >...
{};
//----------------------------------------------------------------------
//
typedef std::tuple< MessageOne, MessageTwo, MessageTen > Foople;
int main()
{
MyMessageHandler< Foople > mmh;
mmh.processMsg( MessageOne() );
}
答案 0 :(得分:4)
您可以按以下方式重写MyMessageHandler
:Live example
template <typename... Ts> struct MyMessageHandler;
template <typename T> struct MyMessageHandler<T>
{
virtual void processMsg(const T&) { }
};
template <typename T, typename...Ts>
struct MyMessageHandler<T, Ts...> : MyMessageHandler<T>, MyMessageHandler<Ts...>
{
using MyMessageHandler<T>::processMsg;
using MyMessageHandler<Ts...>::processMsg;
};
template <typename... Ts>
struct MyMessageHandler<std::tuple<Ts...>> : public MyMessageHandler<Ts...>
{
};
答案 1 :(得分:4)
您可以将转发器添加到MyMessageHandler
的专业化:
template< typename... T >
struct MyMessageHandler< std::tuple< T... > >
: public MyMessageInterface< T >...
{
template< typename U >
void processMsg( const U& u )
{
MyMessageInterface< U >::processMsg( u );
}
};
你需要做这样的事情(或者Jarod42提出的)的原因是,当名称不明确时,基类的虚方法在派生类中是不可见的。通常情况下,您需要添加一个使用声明来提供所需内容,但在您的情况下,转发器可能更容易。
答案 2 :(得分:1)
您必须(不幸地)明确消除您要调用的基类的歧义:
int main()
{
MyMessageHandler< Foople > mmh;
mmh.MyMessageInterface<MessageOne>::processMsg( MessageOne() );
return 0;
}
如果您愿意,可以将演员阵容埋在另一个模板中:
template <typename Handler, typename Message>
void caller(Handler &h, const Message &m)
{
h.MyMessageInterface<Message>::processMsg( m );
}
int main()
{
MyMessageHandler< Foople > mmh;
caller(mmh, MessageOne());
return 0;
}
答案 3 :(得分:0)
问题是成员查找不明确,因为所有MyMessageInterface<T>
都是MyMessageHandler
的直接基类。
我们需要将这组名称引入MyMessageHandler本身,以便我们可以使用这些名称形成重载集。
第一种方法可能是做:using TMessageInterface<T>::processMsg;...
,但当然这不合法。
我的建议是要么做@ Jarod42以递归方式提取processMsg
函数,或者你可以这样做:
template <typename... Ts>
struct MyMessageHandler : MyMessageInterface<Ts>... {
template <typename Msg>
void processMsg(const Msg &msg) {
MyMessageInterface<Msg>::processMsg(msg);
}
};
调用特定的基类“processMsg
。