2011-01-05 95 views
4

我一直試圖調用過載的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>裝飾。其結果是,用字符串參數調用編譯就好了,但與其他類型(例如雙)調用導致以下錯誤:

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>' 

FYI:我使用VC++ 10.0

解決方案: 我從table類丟棄模板scan_index()功能和簡單地寫四個重載函數解決了這個問題(除簽名外,其中三個是相同的)。幸運的是,它們都很短(少於十行),所以它不是很糟糕。這裏

+0

我強烈懷疑你是在一個柯尼希名稱查找問題運行。 – 2011-01-05 18:54:20

+0

潛在的相關:http://stackoverflow.com/questions/4217733/distance-calculation-error-in-c/4218731#4218731 – 2011-01-05 18:56:01

+0

我有一個類似於這裏的問題在這裏:http://stackoverflow.com/questions/3406004 /定義,一個特定的情況下換一個模板化功能-C – Grammin 2011-01-05 18:58:51

回答

7

顯式調用模板成員:

index_table->scan_index<T>(value, [&](uint recno, T n)... 

由於value是模板參數,你應該罰款代替與:

index_table->scan_index(value, [&](uint recno, T n)... 
3

你應該沒有明確指定模板argument-你應該將其留給模板參數推導和重載解析。這應該允許您在原始代碼中發佈的超載被拿起並使用。

1

製備該簡化的測試(對不起,我沒有的C++ 0x編譯大氣壓):

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);更改爲tbl.scan_index(value);將會調用重載版本。

TBH我不知道爲什麼你的模板特不起作用,可能是因爲拉姆達的,不完整的C++ 0x的支持?哪個編譯器?

+0

此無關使用C++ 0x中。這個問題涉及挑選重載,他的lambda代碼是完全有效的。 – Puppy 2011-01-05 19:14:12

+0

「我一直在使用這兩種重載嘗試(如上圖所示)和(下)一個專門的函數模板」 這就是爲什麼我想這件事情與lambda表達式相關 – 2011-01-05 19:19:13

+0

這只是編譯上的Visual C++,因爲一個擴展,允許在一流的專業化。對於其他編譯器(例如GCC),專業化必須在課堂外定義。 (請參閱http://stackoverflow.com/a/2098016/2319122。) – 2016-11-19 15:48:38

0

是不是模板專業化是這樣的:

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 
    }