簡體   English   中英

成員函數重載/模板特化問題

[英]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.

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