为什么std :: sort不接受在函数中声明的比较类 [英] Why std::sort doesn't accept Compare classes declared within a function

查看:154
本文介绍了为什么std :: sort不接受在函数中声明的比较类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在工作,在比较器中写一个函数(稍后移动,当我决定哪里是最好的),并注意到这个特点。我想了一会儿,意识到我不明白为什么代码将无法编译,如果我使用内部比较器,但外部一个很好。



任何解释?



快速测试工具:

  #include< iostream> 
#include< vector>
#include< algorithm>

class CompareMe
{
public:
CompareMe(int in):toCompare(in){}
int toCompare;
};

类比较器
{
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 *>比较;
compare.push_back(new CompareMe(0));
compare.push_back(new CompareMe(1234));
compare.push_back(new CompareMe(163));
compare.push_back(new CompareMe(6));
compare.push_back(new CompareMe(12));

//这样工作,并正确地排列数组
ComparatorsOuter comparator;
std :: sort(compare.begin(),comparing.end(),comparator);

//取消注释下面的排序,它将无法编译。
ComparatorsInner comparatorInner;
// std :: sort(compare.begin(),comparing.end(),comparatorInner);

std :: vector< CompareMe *> :: iterator it;
for(it = comparing.begin(); it!= comparing.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&)'



解决方案

在C ++ 03中,模板参数不能具有内部链接:


[C ++ 03:14.6.4.2/1]:对于依赖于模板参数的函数调用,如果函数name是 unqualified-id 而不是 template-id ,则使用通常的查找规则(3.4.1,3.4.2)找到候选函数, / p>


  • 对于使用非限定名称查找的查找部分(3.4.1)

  • 对于使用关联命名空间(3.4.2)的查找部分,只有在外部链接中找到的函数声明模板定义上下文或模板实例化上下文。

这已更改(问题#561:依赖名称查找中的内部链接函数):


[C ++ 11:C.2.6]: 14.6.4.2

更改:允许具有内部链接的函数的依赖调用
b 原因:过度约束,简化重载解析规则。


导致:


[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)的查找部分,只有在模板中找到的函数声明
  • $ b

(找出缺少的具有外部链接资格。)



因为你的 main():: ComparitorInner& 有内部链接,并且 std :: sort 的实例化类型为模板参数(虽然推导出),但您的代码仅在C ++ 11中有效。


I was at work, writing the Comparators in a function (to move later, when I decided where was best), and noticed this peculiarity. I thought about it for a while, and realized I do not understand exactly why the code will not compile if I use the inner comparators, but the outer one is fine.

Any explanations?

Quick Test harness:

#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;
    }
}

error: no matching function for call to '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&)'

解决方案

In C++03, template arguments could not have internal linkage:

[C++03: 14.6.4.2/1]: For a function call that depends on a template parameter, if the function name is an unqualified-id but not a template-id, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:

  • For the part of the lookup using unqualified name lookup (3.4.1), only function declarations with external linkage from the template definition context are found.
  • For the part of the lookup using associated namespaces (3.4.2), only function declarations with external linkage found in either the template definition context or the template instantiation context are found.

[..]

This was changed (issue #561: "Internal linkage functions in dependent name lookup") in C++11:

[C++11: C.2.6]: 14.6.4.2
Change: Allow dependent calls of functions with internal linkage
Rationale: Overly constrained, simplify overload resolution rules.

resulting in:

[C++11: 14.6.4.2/1]: For a function call that depends on a template parameter, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2, 3.4.3) except that:

  • For the part of the lookup using unqualified name lookup (3.4.1) or qualified name lookup (3.4.3), only function declarations from the template definition context are found.
  • For the part of the lookup using associated namespaces (3.4.2), only function declarations found in either the template definition context or the template instantiation context are found.

[..]

(Spot the missing "with external linkage" qualification.)

Since your main()::ComparitorInner& has internal linkage, and the instantiation of std::sort requires this type to be a template parameter (albeit deduced), your code is only valid in C++11.

这篇关于为什么std :: sort不接受在函数中声明的比较类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆