2012-02-27 69 views
2

我有,我已經超負荷了我的調試類兩種功能:重載函數沒有被使用:

template<class IteratorT> 
    inline debug& 
    operator()(const std::string& name, 
       IteratorT begin, 
       IteratorT end) 
    { 
     _stream << indent(internal) << "g< " << name << " : [ "; 
     for (auto i = begin; i != end; i++) 
     _stream << (*i) << " "; 
     _stream << "] >" << std::endl; 

     return *this; 
    } 

而且

inline debug& 
    operator()(const std::string& name, 
      std::vector<uint8_t>::const_iterator begin, 
      std::vector<uint8_t>::const_iterator end) 
    { 
    _stream << indent(internal) << "u8< " << name << " : [ " << std::hex; 
    std::copy(begin, end, std::ostream_iterator<uint32_t>(_stream, " ")); 
    _stream << "] >" << std::endl; 

    return *this; 
    } 

下面是一個剪斷的如何使用它:

int main() 
{ 
    debug log; 

    std::vector<uint8_t> vec; 
    vec.push_back(0xde); 
    vec.push_back(0xad); 
    vec.push_back(0xc0); 
    vec.push_back(0xde); 

    log("vec", vec.begin(), vec.end()); 
} 

輸出是(因爲它沒有被打印爲十六進制字符,我忽略了未格式化的結果):

g< "vec" : [ ... ] > 

而不是

u8< "vec" : [ de ad c0 de ] > 

出於某種原因編譯器不採摘正確的,重載函數。

$ g++47 --version 
g++47 (GCC) 4.7.0 20120224 (experimental) 

回答

2

代碼中的問題是,重載解析僅考慮函數的參數,而不考慮結果將如何使用。這意味着表達式vec.begin()(相反vec.end())僅考慮vec是非常量向量,因此它使用非常量版本。

雖然存在從std::vector<>::iteratorstd::vector<>::const_iterator的隱式轉換,但此必需的轉換將過載視爲分辨率的最差候選,而不是類型替換爲std::vector<>::iterator的模板函數。

作爲變通方法,可以重載兩個iteratorconst_iterator(最好的解決方案,因爲該解決方案是在剛剛被呼叫者),也可以固定通過迫使矢量通過流延的手段爲常量的調用:static_cast<const std::vector<uint8_T>& >(vec).begin()(這是醜陋的,並需要修復應用於所有通話,這是很難保持)

+0

好的。在旁註中,超載是否比部分專業化更好? – nerozehl 2012-02-27 17:32:34

+0

如果您希望所有向量迭代器在一般情況下具有特殊行爲,將使用部分專用化。不知道是否有可能部分專注於value_type爲uint8_t – CashCow 2012-02-27 17:43:43

+0

@nerozehl的迭代器:你不能部分地專門化一個函數,所以這個問題有一個明確的簡單答案......可能與不可能。現在,您可以將該函數移動爲模板類的靜態非模板成員函數,在這種情況下,您可以部分專門化,以額外代碼爲代價獲得靈活性。但我不確定你會從中得到什麼。另一方面,如果你的意思是一個*完整的*專業化的功能,過載應該是首選,但我不記得爲什麼/它在哪裏重要的具體細節...谷歌它:) – 2012-02-27 17:44:57

2

不幸的是您的專業不會被調用,因爲你逝去的vector<uint8_t>::iteratorvector<uint8_t>::const_iterator,它通過模板找到完全匹配。

要解決這個問題,您可以爲非常量迭代器創建一個重載,或者爲您的向量創建一個常量引用,並在其上調用begin()/end()

+0

不'std :: vector'有'const_iterator begin()const;'應該匹配? – nerozehl 2012-02-27 17:26:54

+0

@nerozehl:閱讀我的答案,重載決議只考慮參數而不考慮結果將如何使用。在這種情況下,因爲矢量不是常量,所以它會選擇'iterator begin();'作爲'vec.begin()'調用的最佳候選。 – 2012-02-27 17:28:14

1

它正在選擇通用版本,因爲您傳遞的是vector<uint8_t>::iterator而不是vector<uint8_t>::const_iterator。您應該添加第三個operator(),採用非const版本並將其傳遞給const