2011-01-05 88 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 
    }