来自可变模板的模糊成员请求
Ambigous member request from variadic template
这对我来说毫无意义。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() );
}
您可以在MyMessageHandler
的专门化中添加转送代理:
template< typename... T >
struct MyMessageHandler< std::tuple< T... > >
: public MyMessageInterface< T >...
{
template< typename U >
void processMsg( const U& u )
{
MyMessageInterface< U >::processMsg( u );
}
};
<<p> 生活例子/strong> 您需要这样做(或Jarod42所建议的)的原因是,当基类的名称有歧义时,基类的虚方法在派生类中是不可见的。通常情况下,你会添加一个using声明来拉入你需要的东西,但在你的情况下,一个forwarder可能更容易。
您可以这样重写MyMessageHandler
:
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...>
{
};
您必须(不幸地)明确地消除要调用的基类的歧义:
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;
}
问题是成员查找是模糊的,因为所有的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
.
相关文章:
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 助记符和指向成员语法的指针
- 用于访问容器<T>数据成员的正确 API
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 嵌套在类中时无法设置成员数据
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 将函数类成员映射到类本身内部
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 成员和成员函数的模糊部分模板专门化
- 自定义成员检测器中的模糊调用
- 来自可变模板的模糊成员请求
- 解决基模板类成员的模糊性