[英]Member function overloading/template specialization issue
我一直試圖調用重載的table::scan_index(std::string, ...)
成員函數,但沒有成功。 為了清楚起見,我刪除了所有不相關的代碼。
我有一個名為table
的類,它有一個名為scan_index()
的重載/模板化成員函數,以便將字符串作為一種特殊情況處理。
class table : boost::noncopyable
{
public:
template <typename T>
void scan_index(T val, std::function<bool (uint recno, T val)> callback) {
// code
}
void scan_index(std::string val, std::function<bool (uint recno, std::string val)> callback) {
// code
}
};
然后有一個hitlist
類,它有許多模板化的成員函數,它們調用table::scan_index(T, ...)
class hitlist {
public:
template <typename T>
void eq(uint fieldno, T value) {
table* index_table = db.get_index_table(fieldno);
// code
index_table->scan_index<T>(value, [&](uint recno, T n)->bool {
// code
});
}
};
最后,代碼全部啟動:
hitlist hl;
// code
hl.eq<std::string>(*fieldno, p1.to_string());
問題是,它不是調用table::scan_index(std::string, ...)
,而是調用模板化版本。 我嘗試過使用重載(如上所示)和專門的函數模板(如下所示),但似乎沒有任何效果。 在盯着這段代碼幾個小時之后,我覺得我錯過了一些明顯的東西。 有任何想法嗎?
template <>
void scan_index<std::string>(std::string val, std::function<bool (uint recno, std::string val)> callback) {
// code
}
更新:我從scan_index()
調用中刪除了<T>
裝飾。 結果是使用字符串參數的調用編譯得很好,但是使用其他類型(例如double)調用會導致以下錯誤:
cannot convert parameter 1 from 'double' to 'std::string'
所以我回到使用模板專業化。 現在我收到這個錯誤:
error C2784: 'void table::scan_index(T,std::tr1::function<bool(uint,T)>)' :
could not deduce template argument for 'std::tr1::function<bool(uint,T)>'
from '`anonymous-namespace'::<lambda5>'
僅供參考:我使用的是VC ++ 10.0
解決方案:我通過從table
類中刪除模板化的scan_index()
函數並簡單地編寫四個重載函數(其中三個除簽名之外的相同)來解決此問題。 幸運的是,它們都很短(少於十行),所以它並不是那么糟糕。
您在此明確調用模板化成員:
index_table->scan_index<T>(value, [&](uint recno, T n)...
由於value
是模板參數,因此您可以將其替換為:
index_table->scan_index(value, [&](uint recno, T n)...
您不應該明確指定模板參數 - 您應該將其留給模板參數推導和重載解析。 這應該允許您在原始代碼中發布的重載被拾取和使用。
准備了這個簡化的測試(抱歉,我沒有C ++ 0x編譯器atm):
class table
{
public:
template <typename T>
void scan_index(T val) {
std::cout << "template\n";
}
template <>
void scan_index<int>(int val) {
std::cout << "specialization\n";
}
void scan_index(int val) {
std::cout << "overloaded\n";
}
};
class hitlist {
public:
template <typename T>
void eq(T value) {
table tbl;
tbl.scan_index<T>(value);
}
};
int main(int argc, char* argv[])
{
int i = 0;
hitlist hl;
hl.eq(i);
return 0;
}
輸出是“專業化”(VC9)。 這是因為hitlist :: eq顯式使用模板版本,因此只考慮模板專業化。 如果你改變tbl.scan_index<T>(value);
to tbl.scan_index(value);
將調用重載版本。
tbh我不知道為什么你的模板專業化不起作用,可能是因為lambda,而不是完整的C ++ 0x支持? 哪個編譯器?
模板專業化不是這樣的:
template <typename T>
void scan_index(T val, std::function<bool (uint recno, T val)> callback) {
// code
}
template <>
void scan_index(std::string val, std::function<bool (uint recno, std::string val)> callback) {
// code
}
這樣C ++編譯器識別scan_index具有特化而不是尋找重載方法。 我相信如果你想要它的編碼方式,你應該把專門的代碼放在模板之前,如下所示:
void scan_index(std::string val, std::function<bool (uint recno, std::string val)> callback) {
// code
}
template <typename T>
void scan_index(T val, std::function<bool (uint recno, T val)> callback) {
// code
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.