我一直试图调用重载的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
}
更新
我从<T>
电话中删除了scan_index()
装饰。结果是带有字符串参数的调用编译得很好,但是使用其他类型调用(例如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
解决方案:
我通过从scan_index()
类中删除模板化的table
函数并简单地编写了四个重载函数(其中三个函数除签名之外相同)来解决此问题。幸运的是,它们都很短(少于十行)所以它并不是那么糟糕。
答案 0 :(得分:7)
您在此处明确调用模板化成员:
index_table->scan_index<T>(value, [&](uint recno, T n)...
由于value
是模板参数,因此您可以将其替换为:
index_table->scan_index(value, [&](uint recno, T n)...
答案 1 :(得分:3)
您不应该明确指定模板参数 - 您应该将其留给模板参数推导和重载解析。这应该允许您在原始代码中发布的重载被拾取和使用。
答案 2 :(得分:1)
准备了这个简化的测试(抱歉,我没有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);
更改为tbl.scan_index(value);
,则会调用重载版本。
tbh我不知道为什么你的模板专业化不起作用,可能是因为lambda,而不是完整的C ++ 0x支持?哪个编译器?
答案 3 :(得分:1)
模板专业化不是:
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
}