2013-12-15 70 views
8

我想創建兩個類(Eigen :: Vector3d和MyVector,協議緩衝區消息)的對象之間的轉換函數,但我想延遲函數體的評估,直到函數被引用(在這一點上兩個類將被定義)。如果函數從未使用過,可以在C++模板函數中使用未定義的類型嗎?

函數應該在稍後定義這兩個類的文件中可調用,並且如果函數從不使用,它不應該導致編譯錯誤。

我:

#include <Eigen/Core> // defines Eigen::Vector3d 

class MyVector { 
    public: int set_x(int x) { x_ = x; } 
    private: int x_; 
} 

void operator<< (MyVector &msg, const Eigen::Vector3d &vec) { 
    msg.set_x(vec.x()); 
} 

,我作爲使用:

MyVector msg; 
Eigen::Vector3d vec(1, 2, 3); 
msg << vec; 

這工作正常,如果函數MyVector後確定,但我想能夠定義的函數,使得它可以包含在缺少MyVector類的翻譯單元中。

我可以在功能改成這樣:

template<typename Msg> 
void operator<< (Msg &msg, ... 

但是這是不可接受的,因爲它適用於其他消息類:

quaternion_msg << Eigen::Vector3d(1, 2, 3); // quaternion has xyz but also w! 

,我想這導致生成錯誤。

有什麼樣的模板魔法可以做到這一點?如果沒有,有沒有更好的方法來爲這個操作符添加MyVector到頭文件(或者它的依賴)?

+0

爲什麼不把操作符<<作爲MyVector的成員? – xis

+0

「,但我希望能夠定義該函數,使其可以包含在缺少MyVector類的翻譯單元中。」您是否嘗試在MyVector類定義爲 – ali

+1

的情況下使用void運算符<<(MyVector&msg,const Eigen :: Vector3d&vec),您可以爲MyVector類型創建模板特化,併爲通用模板存根創建一個代碼,編譯錯誤。 – goldcode

回答

6

您可以在函數模板中使用未定義的類型或函數,只要它們以某種方式依賴於模板參數並在即時點定義即可:在函數模板定義的指針處查找非相關名稱。在實例化過程中查找相關名稱(假定正確實現了兩階段名稱查找)。

另一側,從而防止與其它類型的比小組選定類型的很可能進行成功例示使用SFINAE

class MyVector; 
template <typename Msg> 
typename std::enable_if<std::is_same<Msg, MyVector>::value>::type 
operator<< (Msg& msg, Eigen::Vector3d const& vec) { 
    msg.set_x(vec.x); 
} 

的的std::enable_if<F, T>type只被定義如果Ftrue(和T是默認爲void)。由於std::is_same<Msg, MyVector>::value變成true僅當MsgMyVector該運算符僅在用MyVector實例化時才被定義。另一方面,它在被實例化時被定義爲有希望定義的點MyVector

但是,由於MyVector是在接口中命名的,因此它的名稱需要聲明,儘管它不需要定義。如果MyVector可以專門化一個特質,在這種情況下命名爲MyVector的類型可以被延遲直到它被定義並且該特徵被專門化,這可以避免這種需要。做這樣的事情可能很重要,如果MyVector實際上是一個默認參數的模板,因爲它們不能被轉發聲明。

+0

這完全符合我的要求,現在我知道很多我在C++ 11中錯過的新的[類型操作](http://en.cppreference.com/w/cpp/types)。謝謝! – user3105361

1

創建一個專門用於模板化操作員內的小型模板化類。

即:

template <typename MSG> 
struct Convertor; // generic causes compiler error 

template<> 
struct Convertor<MyVector> { 
    static void Convert(MyVector msg, Eigen::vector3d const& vec) { 
    msg.set_x(vec.x()); 
    } 
}; 

template<typename Msg> 
void operator<< (Msg &msg, const Eigen::Vector3d &vec) { 
    Convertor<Msg>::Convert(msg, vec); 
} 

如果需要,您可以擴大這種模式更多的模板參數,並專注於只有你想要的轉換。

+0

我嘗試了一個類似的專業化,只有一個功能,並得到不完整類型的錯誤。我與您發佈的代碼有同樣的問題。我將在下一條評論中包含我嘗試的代碼。我替換了Eigen類來簡化它。這裏是我在未定義消息類時得到的錯誤: 'test.cc:在靜態成員函數'static void轉換器 :: Convert(MyMsg&,const NotAMessage&)': test.cc:19:8:錯誤:使用不完整的類'class MyMsg' msg.set_x(vec.x()); test.cc:11:7:error:'class MyMsg'的前向聲明 class MyMsg; ^ – user3105361

+0

// class MyMsg {public:int set_x(int x){x_ = x; } // private:int x_; //}; class NotAMessage { public:int x()const {return x_; } private:int x_; }; class MyMsg; template struct Convertor; //通用原因編譯器錯誤 模板<> struct轉換器 { static void轉換(MyMsg&msg,NotAMessage const&vec){msg.set_x(vec。X()); } }; template void operator <<(Msg&msg,const NotAMessage&vec){ Convertor :: Convert(msg,vec); } – user3105361

+0

你應該把類MyVector – Michael

相關問題