我在工作,在一个函数中编写比较器(稍后移动,当我决定哪里最好的时候),并注意到这个特性。我想了一会儿,并意识到我不明白为什么代码不能编译,如果我使用内部比较器,但外部的一个很好。
有任何解释吗?
快速测试工具:
#include <iostream>
#include <vector>
#include <algorithm>
class CompareMe
{
public:
CompareMe(int in) : toCompare(in){}
int toCompare;
};
class Comparators
{
public:
bool operator()(CompareMe * first, CompareMe * second)
{
return first->toCompare < second->toCompare;
}
};
class ComparatorsOuter : public Comparators{};
int main()
{
class ComparatorsInner : public Comparators{};
std::vector<CompareMe *> compares;
compares.push_back(new CompareMe(0));
compares.push_back(new CompareMe(1234));
compares.push_back(new CompareMe(163));
compares.push_back(new CompareMe(6));
compares.push_back(new CompareMe(12));
//This works, and properly sorts the array
ComparatorsOuter comparator;
std::sort(compares.begin(), compares.end(), comparator);
//Uncomment out the sort below and it will not compile.
ComparatorsInner comparatorInner;
//std::sort(compares.begin(), compares.end(), comparatorInner);
std::vector<CompareMe *>::iterator it;
for(it = compares.begin(); it != compares.end(); ++it)
{
std::cout << (*it)->toCompare << std::endl;
}
}
错误:没有匹配函数来调用“
sort(__gnu_cxx::__normal_iterator<CompareMe**, std::vector<CompareMe*, std::allocator<CompareMe*> > >, __gnu_cxx::__normal_iterator<CompareMe**, std::vector<CompareMe*, std::allocator<CompareMe*> > >, main()::ComparitorInner&)
”
答案 0 :(得分:10)
在C ++ 03中,模板参数不能具有内部链接:
[C++03: 14.6.4.2/1]:
对于依赖于模板参数的函数调用,如果函数名称是 unqualified-id 而不是 template-id ,则使用通常的查找规则(3.4.1,3.4.2)找到候选函数,但:
- 对于使用非限定名称查找的部分查找(3.4.1),仅找到模板定义上下文中带有外部链接的函数声明。
- 对于使用关联命名空间(3.4.2)的查找部分,只能找到在模板定义上下文或模板实例化上下文中找到的具有外部链接的函数声明。
[..]
在C ++ 11中更改了(问题#561: "Internal linkage functions in dependent name lookup"):
[C++11: C.2.6]:
14.6.4.2
更改:允许具有内部链接的功能的相关调用
理由:过度约束,简化了重载决策规则。
导致:
[C++11: 14.6.4.2/1]:
对于依赖于模板参数的函数调用,使用通常的查找规则(3.4.1,3.4.2,3.4.3)找到候选函数,除了:
- 对于使用非限定名称查找(3.4.1)或限定名称查找(3.4.3)的查找部分,只能找到模板定义上下文中的函数声明。 /强>
- 对于使用关联命名空间(3.4.2)的查找部分,只能找到模板定义上下文或模板实例化上下文中找到的函数声明。
[..]
(找出缺少的“与外部链接”资格。)
由于您的main()::ComparitorInner&
具有内部链接,并且std::sort
的实例化要求此类型为模板参数(尽管已推断),因此您的代码仅在C ++ 11中有效。
答案 1 :(得分:3)
你的代码在C ++ 11中很好用;在C ++ 03中使用局部类型作为模板参数存在限制。