std ::用本地类型比较排序 [英] std::sort with local type Compare

查看:230
本文介绍了std ::用本地类型比较排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下示例

  //文件mysort.cc 
#include< string>
#include< vector>
#include< algorithm>
#include< string.h>

void mysort(const char ** tab,unsigned size){
std :: vector< int> vecix;
vecix.resize(size);
struct CompareIndex {
const char ** t;
CompareIndex(const char ** p):t(p){};
bool operator()(int l,int r){
return strcmp(t [l],t [r])<0;
}
};
CompareIndex compix(tab); (unsigned ix = 0; ix< size; ix ++)vecix [ix] = ix;
;
std :: stable_sort(vecix.begin(),vecix.end(),compix);
std :: vector< const char *> vecstr;
vecstr.resize(size); (unsigned ix = 0; ix< size; ix ++)vecstr [ix] = tab [vecix [ix]];
;
for(unsigned ix = 0; ix< size; ix ++)tab [ix] = vecstr [ix];
}

无法编译(在Debian / Sid / x86- C ++ 03标准中的64)

  mysort.cc:在函数'void mysort(const char **,unsigned int) ':
mysort.cc:19:58:错误:没有匹配函数调用
'stable_sort(std :: vector< int> :: iterator,
std :: vector< int> ; :: iterator,
mysort(const char **,unsigned int):: CompareIndex&)'
std :: stable_sort(vecix.begin(),vecix.end(),compix);
^


从/usr/include/c++/4.8/algorithm:62:0包含的文件中,从mysort.cc:4 $ b $包含
b /usr/include/c++/4.8/bits/stl_algo.h:5682:5:note:
template< class _RAIter,class _Compare>
void std :: stable_sort(_RAIter,_RAIter,_Compare)
stable_sort(_RandomAccessIterator __first,_RandomAccessIterator __last,
^
/usr/include/c++/4.8/bits/stl_algo。 h:5682:5:note:
template argument deduction / substitution failed:
mysort.cc:代替'template< class _RAIter,class _Compare>
void std :: stable_sort(_RAIter ,_RAIter,_Compare)
[with _RAIter = __gnu_cxx :: __ normal_iterator< int *,std :: vector< int>;
_Compare = mysort(const char **,unsigned int):: CompareIndex ]':
mysort.cc:19:58:需要从这里
mysort.cc:19:58:error:模板参数为
'template< class _RAIter,class _Compare>
void std :: stable_sort(_RAIter,_RAIter,_Compare)'
使用本地类型'mysort(const char **,unsigned int):: CompareIndex'
std :: stable_sort(vecix.begin( ),vecix.end(),compix);
^
mysort.cc:19:58:错误:试图实例化
'模板< class _RAIter,class _Compare>
void std :: stable_sort(_RAIter,_RAIter,_Compare)'

以上内容已编译 GCC 4.8 使用

  g ++ -Wall -c mysort.cc 

相同的错误

  g ++ -std = c ++ 03 -Wall -c mysort.cc 


或与

  g ++ -std = c ++ 98 -Wall -c mysort.cc 

但是没有错误

  g ++ -std = c ++ 11 -c mysort.cc 

给定我的 g ++ -v 是一个 gcc版本4.8.2(Debian 4.8.2-12 )



但带有 Clang / LLVM 3.4 编译时使用

  clang ++ -Wall -c mysort.cc 

我只收到警告:

  mysort.cc:19:7:warning:模板参数使用本地
类型'CompareIndex'
[-Wlocal-type-template-args]
std :: stable_sort(vecix.begin(),vecix.end(),compix);
^ ~~
1生成警告。

(当传递 -std时,我仍然只会得到一个警告而不是错误= c ++ 03 -std = c ++ 98 to clang ++ 但不是警告与 clang ++ -std = c ++ 11

所以我的问题是:为什么错误是由GCC和Clang的警告?我的代码是否合法,没有未定义的行为(w.r.t. C ++ 03标准)?我应该在我的编译器中创建 CompareIndex 全局 struct 吗?



motivations



当然,这是对C字符串数组进行排序的一种愚蠢的方法。
实际代码有点不同。实际上,我试图在我的中使用 std :: stable_sort > MELT 插件(用于扩展和定制GCC的领域特定语言)。 MELT正在生成C ++代码并且有一个复制 垃圾收集器 a>(所以指针由GC移动)。因此,我需要使用索引数组进行排序:比较函数实际上调用MELT闭包(可以在任意时刻触发复制GC),所以我需要按索引进行排序(而不是通过原始指针)。我希望保持由MELT生成的C ++代码符合编译GCC所需的C ++标准(03或98)。


$ b

work-around



感谢 juanchopanza的回答我已通过移动<$ c的声明解决了该问题$ c> CompareIndex 在全局范围之前 mysort



我只是承担了GCC MELT分支的svn修订版206748;其文件 gcc / melt / warmelt-base.melt 现在包含 multiple_sort_new MELT函数(用于替换<$ c $使用 std :: stable_sort 和一个全局 Melt_Sort_Compare_Index 在C + +代码中使用本地类型。

解决方案

+03。

根据ISO / IEC 14882, 14.3.1模板类型参数[temp.arg.type]


一个本地类型,一个没有链接的类型,一个未命名的类型或者一个类型
由这些类型中的任何一个复合而成,不能用作


给出的例子包含以下几行:

 模板< typename T> struct Foo {}; 

void foo()
{
struct Bar {};
Foo< Bar> B1; //错误:用作模板参数的本地类型
Foo< Bar *> X4; //错误:用作模板参数的本地类型指针
}

这个限制有在C ++ 11中被解除。

The following example

// file mysort.cc
#include <string>
#include <vector>
#include <algorithm>
#include <string.h>

void mysort (const char**tab, unsigned size) {
  std::vector<int> vecix;
  vecix.resize(size);
  struct CompareIndex {
    const char**t;
    CompareIndex(const char**p) : t(p) {};
    bool operator() (int l, int r)  {
      return strcmp(t[l], t[r])<0;
    }
  };
  CompareIndex compix(tab);
  for (unsigned ix=0; ix<size; ix++) vecix[ix] = ix;
  std::stable_sort(vecix.begin(), vecix.end(), compix);
  std::vector<const char*> vecstr;
  vecstr.resize(size);
  for (unsigned ix=0; ix<size; ix++) vecstr[ix] = tab[vecix[ix]];
  for (unsigned ix=0; ix<size; ix++) tab[ix] = vecstr[ix];
}    

fails to compile (using GCC 4.8.2 on Debian/Sid/x86-64 in C++03 standard)

mysort.cc: In function 'void mysort(const char**, unsigned int)':
mysort.cc:19:58: error: no matching function for call to 
      'stable_sort(std::vector<int>::iterator, 
                   std::vector<int>::iterator, 
                   mysort(const char**, unsigned int)::CompareIndex&)'
   std::stable_sort(vecix.begin(), vecix.end(), compix);
                                                      ^


In file included from /usr/include/c++/4.8/algorithm:62:0,
                 from mysort.cc:4:
/usr/include/c++/4.8/bits/stl_algo.h:5682:5: note: 
       template<class _RAIter, class _Compare>
                void std::stable_sort(_RAIter, _RAIter, _Compare)
     stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
     ^
/usr/include/c++/4.8/bits/stl_algo.h:5682:5: note:   
    template argument deduction/substitution failed:
mysort.cc: In substitution of 'template<class _RAIter, class _Compare>
     void std::stable_sort(_RAIter, _RAIter, _Compare)
     [with _RAIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >;
           _Compare = mysort(const char**, unsigned int)::CompareIndex]':
mysort.cc:19:58:   required from here
mysort.cc:19:58: error: template argument for
    'template<class _RAIter, class _Compare> 
         void std::stable_sort(_RAIter, _RAIter, _Compare)'
     uses local type 'mysort(const char**, unsigned int)::CompareIndex'
       std::stable_sort(vecix.begin(), vecix.end(), compix);
                                                          ^
mysort.cc:19:58: error:   trying to instantiate
            'template<class _RAIter, class _Compare>
                     void std::stable_sort(_RAIter, _RAIter, _Compare)'

The above was compiled with GCC 4.8 using

  g++ -Wall -c mysort.cc

I am getting the same error with

  g++ -std=c++03 -Wall -c mysort.cc

or with

  g++ -std=c++98 -Wall -c mysort.cc

but no errors with

  g++ -std=c++11 -c mysort.cc

given that my g++ -v is a gcc version 4.8.2 (Debian 4.8.2-12)

but with Clang/LLVM 3.4 compiling with

  clang++ -Wall -c mysort.cc

I'm getting only a warning:

  mysort.cc:19:7: warning: template argument uses local 
                  type 'CompareIndex'
                [-Wlocal-type-template-args]
  std::stable_sort(vecix.begin(), vecix.end(), compix);
  ^~~
  1 warning generated.

(and I still get only a warning not an error when passing -std=c++03 or -std=c++98 to clang++ but no warnings with clang++ -std=c++11)

so my question is: why the error by GCC and the warning by Clang? Is my code legal and without undefined behavior (w.r.t. the C++03 standard)? Should I make my CompareIndex a global struct in my compilation unit?

motivations

Of course, this is a silly way to sort an array of C strings. The real code is a bit different. In fact, I am trying to use std::stable_sort in my MELT plugin (a domain specific language to extend and customize GCC). MELT is generating C++ code and has a copying garbage collector (so pointers are moved by the GC). Hence, I need to sort using an array of indexes: the compare function in fact calls a MELT closure (which could trigger the copying GC at arbitrary moment), so I need to sort by indexes (and not by raw pointers). I want to keep the C++ code generated by MELT conforming to the C++ standard (03 or 98) required to compile GCC.

work-around

Thanks to juanchopanza's answer I've solved the issue by moving the declaration of CompareIndex at global scope before mysort.

I just committed the svn revision 206748 of the MELT branch of GCC; its file gcc/melt/warmelt-base.melt contains now a multiple_sort_new MELT function (to replace multiple_sort when it is working well) using std::stable_sort, and a global Melt_Sort_Compare_Index class in the generated C++ code.

解决方案

Using local types as template arguments is not allowed in C++03.

From ISO/IEC 14882, 14.3.1 Template type arguments [temp.arg.type]:

A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter.

The example given is along these lines:

template <typename T> struct Foo {};

void foo()
{
  struct Bar {};
  Foo<Bar> b1;   // error: local type used as template-argument
  Foo<Bar*> x4;  // error: pointer to local type used as template-argument
}

This restriction has been lifted in C++11.

这篇关于std ::用本地类型比较排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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