简体   繁体   English

成员函数重载/模板特化问题

[英]Member function overloading/template specialization issue

I've been trying to call the overloaded table::scan_index(std::string, ...) member function without success. 我一直试图调用重载的table::scan_index(std::string, ...)成员函数,但没有成功。 For the sake of clarity, I have stripped out all non-relevant code. 为了清楚起见,我删除了所有不相关的代码。

I have a class called table which has an overloaded/templated member function named scan_index() in order to handle strings as a special case. 我有一个名为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
    }
};

Then there is a hitlist class which has a number of templated member functions which call table::scan_index(T, ...) 然后有一个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
        });
    }
};

And, finally, the code which kicks it all off: 最后,代码全部启动:

hitlist hl;
// code
hl.eq<std::string>(*fieldno, p1.to_string());

The problem is that instead of calling table::scan_index(std::string, ...) , it calls the templated version. 问题是,它不是调用table::scan_index(std::string, ...) ,而是调用模板化版本。 I have tried using both overloading (as shown above) and a specialized function template (below), but nothing seems to work. 我尝试过使用重载(如上所示)和专门的函数模板(如下所示),但似乎没有任何效果。 After staring at this code for a few hours, I feel like I'm missing something obvious. 在盯着这段代码几个小时之后,我觉得我错过了一些明显的东西。 Any ideas? 有任何想法吗?

    template <>
    void scan_index<std::string>(std::string val, std::function<bool (uint recno, std::string val)> callback) {
        // code
    }

Update: I dropped the <T> decoration from the scan_index() call. 更新:我从scan_index()调用中删除了<T>装饰。 The result was that the calls with a string parameter compile just fine, but calls with other types (eg double) resulted in the following error: 结果是使用字符串参数的调用编译得很好,但是使用其他类型(例如double)调用会导致以下错误:

cannot convert parameter 1 from 'double' to 'std::string'

So I went back to using template specialization. 所以我回到使用模板专业化。 Now I get this error: 现在我收到这个错误:

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: I am using VC++ 10.0 仅供参考:我使用的是VC ++ 10.0

Solution: I fixed this problem by dropping the templated scan_index() function from the table class and simply writing four overloaded functions (three of which are identical except for the signature). 解决方案:我通过从table类中删除模板化的scan_index()函数并简单地编写四个重载函数(其中三个除签名之外的相同)来解决此问题。 Luckily, they're all pretty short (less than ten lines) so it's not so bad. 幸运的是,它们都很短(少于十行),所以它并不是那么糟糕。

You explicitly call templated member here: 您在此明确调用模板化成员:

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

Since value is the template parameter you should be fine replacing that with: 由于value是模板参数,因此您可以将其替换为:

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

You shouldn't explicitly specify the template argument- you should leave it to template argument deduction and overload resolution. 您不应该明确指定模板参数 - 您应该将其留给模板参数推导和重载解析。 This should allow the overload you posted in the very original code to be picked up and used. 这应该允许您在原始代码中发布的重载被拾取和使用。

prepared this simplified test (sorry, I don't have C++0x compiler atm): 准备了这个简化的测试(抱歉,我没有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;
}

output is "specialization" (VC9). 输出是“专业化”(VC9)。 it's because hitlist::eq explicitly uses template version, so only template specialization will be considered. 这是因为hitlist :: eq显式使用模板版本,因此只考虑模板专业化。 if you change tbl.scan_index<T>(value); 如果你改变tbl.scan_index<T>(value); to tbl.scan_index(value); to tbl.scan_index(value); overloaded version will be called. 将调用重载版本。

tbh I don't know why your template specialization doesn't work, probably because of lambda, not complete C++0x support? tbh我不知道为什么你的模板专业化不起作用,可能是因为lambda,而不是完整的C ++ 0x支持? which compiler? 哪个编译器?

Isn't the template specialisation be something like: 模板专业化不是这样的:

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
}

This way C++ compiler recognizes scan_index has a specialisation rather than looking for the overloaded method. 这样C ++编译器识别scan_index具有特化而不是寻找重载方法。 And I believe if you wanted it the way you can coded, you should probably put the specialised code before the template like this: 我相信如果你想要它的编码方式,你应该把专门的代码放在模板之前,如下所示:

    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