簡體   English   中英

變量模板繼承,成員函數重載

[英]Variadic template inheritence, member function overloading

我正在嘗試使用可變參數模板重寫模板化的類http://docs.ros.org/hydro/api/rviz/html/c++/message__filter__display_8h_source.html以與多種消息類型一起使用。

我的第一個問題是我如何使用可變參數模板重寫下面的示例代碼,因此它可以與任意數量的模板參數一起使用,而不僅僅是2。

我在父類中需要什么:

  • 每個模板化類型的虛擬成員函數processMessage
  • 每個模板化類型的每個incomingMessage的成員函數
  • 每個模板化類型的成員變量。 (稍后將成為ROS中該MessageType主題的訂閱者)

因此,如果使用2個模板化類型調用,則可變參數基類應該編譯為如下所示:

包括:

#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()。 通過更多的工作,也可能有一種解決方法。

問題是, Parent一個特化中的incomingMessage聲明隱藏了基類特化中的聲明; 因此,您的Child類中唯一可用的重載是對於直接基類中的string

最簡單的解決方案是向Parent添加using聲明以使所有重載可用:

using Parent<Tail...>::incomingMessage;

你還需要在“root”專門化中聲明一個聲明來支持這個:

template<> struct Parent<>{
    void incomingMessage(); // No need for a definition
};

您可能還希望將messages_received_移動到“root”特化中,以便所有消息類型都有一個計數器,而不是每種類型的一個計數器。 如果你這樣做,請記住它是一個依賴名稱,因此派生的特化必須將其稱為this->messages_received_Parent<>::messages_received_

Child繼承Parent<std::string, int> ,它從template <class... Elements> class Parent實例化。 嗯,讓我們看看編譯器如何即時發布它。

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取消隱藏超類的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_);
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM