C++ 来自可变模板的模棱两可成员请求
这对我来说毫无意义。GCC抱怨下面在C++ 来自可变模板的模棱两可成员请求,c++,templates,c++11,variadic-templates,C++,Templates,C++11,Variadic Templates,这对我来说毫无意义。GCC抱怨下面在main()中对processMsg()的调用是不明确的,即使创建的所有模板processMsg()调用都被报告为候选调用。我尝试了三种不同的方法来实现这个可变模板原型,它们都会导致相同的请求不明确问题。当我将模板实现分解为不同的情况时,我确实更接近了,但是我发现编译器只能解析元组中的第一个查找 我贴了一个小例子。我肯定我错过了一些简单的东西 #include <tuple> //---------------------------------
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() );
}
#包括
//----------------------------------------------------------------------
//
类消息库
{
公众:
MessageBase(const int_id):m_id(_id){}
虚拟int getMessageID()常量{return(m_id);}
私人:
const int m_id;
};
#定义消息(名称、VAL)\
类消息##名称:public MessageBase{\
公众:\
Message##NAME():MessageBase(VAL){}\
};
信息(一,1);
信息(二,二);
信息(十,十);
//----------------------------------------------------------------------
//
模板
结构MyMessageInterface{
虚空进程msg(const T&T){}
};
模板<类型名。。。T>
结构MyMessageHandler:公共MyMessageInterface。。。
{};
模板<类型名。。。T>
结构MyMessageHandler>
:public MyMessageInterface。。。
{};
//----------------------------------------------------------------------
//
typedef std::tupleFoople;
int main()
{
MyMessageHandlermmh;
processMsg(MessageOne());
}
不幸的是,您必须明确地消除要调用的基类的歧义:
int main()
{
MyMessageHandler< Foople > mmh;
mmh.MyMessageInterface<MessageOne>::processMsg( MessageOne() );
return 0;
}
intmain()
{
MyMessageHandlermmh;
MyMessageInterface::processMsg(MessageOne());
返回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;
}
模板
无效调用方(处理程序&h、常量消息&m)
{
h、 MyMessageInterface::processMsg(m);
}
int main()
{
MyMessageHandlermmh;
调用者(mmh,MessageOne());
返回0;
}
您可以按如下方式重写MyMessageHandler
:
模板结构MyMessageHandler;
模板结构MyMessageHandler
{
虚空进程msg(常数T&){}
};
模板
结构MyMessageHandler:MyMessageHandler,MyMessageHandler
{
使用MyMessageHandler::processMsg;
使用MyMessageHandler::processMsg;
};
模板
结构MyMessageHandler:公共MyMessageHandler
{
};
您可以将转发器添加到MyMessageHandler
的专门化中:
template< typename... T >
struct MyMessageHandler< std::tuple< T... > >
: public MyMessageInterface< T >...
{
template< typename U >
void processMsg( const U& u )
{
MyMessageInterface< U >::processMsg( u );
}
};
模板
结构MyMessageHandler>
:public MyMessageInterface。。。
{
模板
void processMsg(常量U&U)
{
MyMessageInterface::processMsg(U);
}
};
需要这样做的原因(或Jarod42建议的)是,当名称不明确时,基类的虚拟方法在派生类中不可见。通常,您会添加一个using声明来获取所需内容,但在您的情况下,转发器可能更容易。问题在于成员查找不明确,因为所有
MyMessageInterface
都是MyMessageHandler
的直接基类
我们需要将名称集拉入MyMessageHandler本身,以便可以使用这些名称形成重载集
第一种方法可能是这样做:使用TMessageInterface::processMsg但是那当然是不合法的
我的建议是要么像@Jarod42那样递归地拉入processMsg
函数,要么您可以:
template <typename... Ts>
struct MyMessageHandler : MyMessageInterface<Ts>... {
template <typename Msg>
void processMsg(const Msg &msg) {
MyMessageInterface<Msg>::processMsg(msg);
}
};
模板
结构MyMessageHandler:MyMessageInterface。。。{
模板
无效处理消息(常量消息和消息){
MyMessageInterface::processMsg(msg);
}
};
它调用特定的基类“processMsg
最好将模板方法直接放在类中:template struct MyMessageHandler:public MyMessageInterface。。。{template void processMsg(const T2&t){MyMessageInterface::processMsg(t);}代码>()解释一下为什么这会解决它,这将有助于理解它。嗯。。。因此,计划是(下一步)从上面派生一个具体的MessageHandler对象,并在派生类中重载processMsg()调用。我猜这样不行?(我试过了,但似乎没有。)@RMHarris157我们在公司代码库中使用的一个选项是调用虚拟函数v_processMsg
,该函数允许稍后将其覆盖,并将非虚拟的processMsg
转发给它。这样,接口/转发器processMsg
就可以放在正确的位置,并且不会干扰虚拟部分和类层次结构
并将转发器中的调用更改为MyMessageInterface::vProcessMsg(_msg)代码>当我试图编译包含上述派生定义的.C时,链接器抱怨它找不到元组中每个类的vProcessMsg的基类实现。我是否错过了另一层间接的东西?
template <typename... Ts>
struct MyMessageHandler : MyMessageInterface<Ts>... {
template <typename Msg>
void processMsg(const Msg &msg) {
MyMessageInterface<Msg>::processMsg(msg);
}
};