下面的例子
// 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];
}
无法编译(在 C++03 标准的 Debian/Sid/x86-64 上使用 GCC 4.8.2)
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)'
以上内容是用GCC 4.8 http://gcc.gnu.org/gcc-4.8/ using
g++ -Wall -c mysort.cc
我遇到了同样的错误
g++ -std=c++03 -Wall -c mysort.cc
or with
g++ -std=c++98 -Wall -c mysort.cc
但没有错误
g++ -std=c++11 -c mysort.cc
鉴于我的g++ -v
is a gcc version 4.8.2 (Debian 4.8.2-12)
但与铿锵/LLVM 3.4 http://llvm.org/releases/3.4/docs/ReleaseNotes.html编译用
clang++ -Wall -c mysort.cc
我只收到警告:
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.
(并且在通过时我仍然只收到警告而不是错误-std=c++03
or -std=c++98
to clang++
但没有警告clang++ -std=c++11
)
所以我的问题是:为什么 GCC 会出现错误,而 Clang 会出现警告?我的代码合法并且没有未定义的行为(w.r.t. C++03 标准)吗?我应该让我的CompareIndex
一个全球性的struct
在我的编译单元中?
动机
当然,这是一种对 C 字符串数组进行排序的愚蠢方法。
真正的代码有点不同。事实上,我正在尝试使用std::stable_sort
in my MELT http://gcc-melt.org/插件(用于扩展和自定义 GCC 的特定领域语言)。 MELT 正在生成 C++ 代码并具有copying 垃圾收集器 http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29(因此指针由 GC 移动)。因此,我需要使用索引数组进行排序:比较函数实际上调用了 MELT 闭包(它可以在任意时刻触发复制 GC),因此我需要按索引(而不是原始指针)排序。我想让 MELT 生成的 C++ 代码符合编译 GCC 所需的 C++ 标准(03 或 98)。
解决方法
谢谢胡安乔潘萨的回答 https://stackoverflow.com/a/21201894/841108我通过移动声明解决了这个问题CompareIndex
之前在全球范围内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.