std ::用本地类型比较排序 [英] std::sort with local type Compare
问题描述
以下示例
//文件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
toclang ++
但不是警告与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)。
$ bwork-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 $时,使用
在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 agcc 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
toclang++
but no warnings withclang++ -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 globalstruct
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 beforemysort
.I just committed the svn revision 206748 of the MELT branch of GCC; its file
gcc/melt/warmelt-base.melt
contains now amultiple_sort_new
MELT function (to replacemultiple_sort
when it is working well) usingstd::stable_sort
, and a globalMelt_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屋!