可变模板继承,成员函数重载
Variadic template inheritence, member function overloading
我正在尝试重写模板化的类http://docs.ros.org/hydro/api/rviz/html/c++/message__filter_display_8h_source.html与多种消息类型一起使用,使用可变模板。
我的第一个问题是如何使用可变模板重写下面的示例代码,以便它可以与任意数量的模板参数一起使用,而不仅仅是2个。
我在家长班需要什么:
- 每个模板化类型的虚拟成员函数CCD_ 1
- 每个模板化类型的每个
incomingMessage
的成员函数 - 每个模板化类型的成员变量。(稍后将成为ROS中该MessageType主题的订阅者)
因此,如果用2个模板化类型调用,variadic基类应该编译成这样:
包括:
#include<string>
#include<sstream>
#include<iostream>
using namespace std;
工作代码(常用模板):
template<class MessageType1,class MessageType2> class Parent{
public:
Parent() : messages_received_(0){}
virtual void processMessage(MessageType1 msg) = 0;
virtual void processMessage(MessageType2 msg) = 0;
void incomingMessage(MessageType1 msg){
processMessage(msg);
incr();
}
void incomingMessage(MessageType2 msg){
processMessage(msg);
incr();
}
private:
void incr(){
cout<<"received "<<++messages_received_<<endl;;
}
MessageType1 sub1_;
MessageType2 sub2_;
int messages_received_;
};
不工作(可变):
template<class... Elements> class Parent;
template<> class Parent<>{};
template<class Head, class... Tail> class Parent<Head, Tail...> : public Parent<Tail...> {
public:
Parent() : messages_received_(0){}
virtual void processMessage(Head msg) = 0;
void incomingMessage(Head msg){
processMessage(msg);
incr();
}
private:
void incr(){
cout<<"received "<<++messages_received_<<endl;;
}
Head sub1_;
int messages_received_;
};
编译失败,出现:
g++ variadic.cpp --std=c++0x
variadic.cpp: In function ‘int main()’:
variadic.cpp:52:33: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
/usr/include/c++/4.6/bits/basic_string.h:485:7: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]’ [-fpermissive]
所以我想,不知何故,成员函数processMessage
只编译到processMessage(std::string s)
,而没有编译到重载版本processMessage(int a)
;
示例用法:
class Child : public Parent<std::string, int> {
public:
void processMessage(std::string msg){
cout<<"string: "<<msg<<endl;
}
void processMessage(int msg){
cout<<"int: "<<msg<<endl;
}
};
int main()
{
Child myMfd;
myMfd.incomingMessage(42);
myMfd.incomingMessage("abc");
return 0;
}
如何解决此问题?
我还没有测试过这个,但它应该在下面的某个地方:
template<typename ...Args> class Parent;
template<> class Parent<> {
public:
void incr();
void incomingMessage() {}
};
template<typename MessageType, typename ...Args>
class Parent<MessageType, Args...> : public Parent<Args...> {
public:
virtual void processMessage(MessageType msg)=0;
using Parent<Args...>::incomingMessage;
void incomingMessage(MessageType msg)
{
processMessage(msg);
this->incr();
}
};
这并不完美,您需要从上一个类"向上传播"incomingMessage,以便在"顶级范围"中正确解析,因此需要在根超类中使用一个丑陋的incomingMessage()。有了更多的工作,也许也有办法解决这个问题。
问题是Parent
的一个专门化中incomingMessage
的声明隐藏了基类专门化中的声明;所以Child
类中唯一可用的重载是直接基类中string
的重载。
最简单的解决方案是在processMessage
0中添加一个using声明,以使所有重载都可用:
using Parent<Tail...>::incomingMessage;
你还需要在"根"专业化中声明来支持这一点:
template<> struct Parent<>{
void incomingMessage(); // No need for a definition
};
您可能还想将messages_received_
移到"根"专用化中,这样就可以为所有消息类型提供一个计数器,而不是为每种类型提供一。如果你这样做,请记住它是一个从属名称,因此衍生专业必须将其称为this->messages_received_
或Parent<>::messages_received_
。
Child
继承了从template <class... Elements> class Parent
实例化的Parent<std::string, int>
。让我们看看编译器如何实例化它
template<>
class Parent<int>
: public Parent<>
{
// ...
virtual void processMessage(int msg) = 0;
void incomingMessage(int msg)
{
processMessage(msg);
incr();
}
// ...
};
template<>
class Parent<std::string, int>
: public Parent<int>
{
// ...
virtual void processMessage(std::string msg) = 0;
void incomingMessage(std::string msg)
{
processMessage(msg);
incr();
}
// ...
};
class Child : public Parent<std::string, int>
{
// ...
祖父母类Parent<int>
当然有void incomingMessage(int)
,但父母级Parent<std::string>, int>
有void incomingMessage(std::string)
,它隐藏了Parent<int>::incomingMessage(int)
。
那该怎么办?-只是通过"使用"它来取消隐藏超类的incomingMessage
。
template<class Head, class... Tail>
class Parent<Head, Tail...>
: public Parent<Tail...>
{
public:
using Parent<Tail...>::incomingMessage;
// ...
当然,伪根Parent
也应该具有incomingMessage
。
template <> class Parent<>
{
public:
// to forbid call dummy `incomingMessage`.
class dummy_ { private: dummy_() = delete; };
void incomingMessage(dummy_);
};
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 将公共但非静态的成员函数与ALGLIB集成
- 使用指向成员的指针将成员函数作为参数传递
- 将重载的成员函数传递给函数模板
- 我不小心调用了一个没有自己类对象的成员函数.但这是怎么回事呢
- 如何在C++中使用非静态成员函数作为回调函数
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 关联容器的下界复杂性:成员函数与非成员函数
- 在 C++ 中用派生类型重写成员函数
- 链表的泛型函数remove()与成员函数remove)
- 如何将lambda作为模板类的成员函数参数
- constexpr构造函数需要常量成员函数时出现问题
- 将自由函数绑定为类成员函数
- 区分非成员函数和头文件中的成员函数
- 如何从子成员函数修改父公共成员变量
- 保留对其他类的成员函数的引用
- 在运算符重载定义中使用成员函数(const错误)
- 内联如何影响模块接口中的成员函数
- 将成员函数指针作为参数传递给模板方法