以下示例
// 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)'
以上是使用<{p}编译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 version 4.8.2 (Debian 4.8.2-12)
但是Clang/LLVM 3.4使用
进行编译 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
或-std=c++98
传递给clang++
时,我仍然只收到警告而不是错误,但clang++ -std=c++11
没有警告
所以我的问题是:为什么GCC的错误和Clang的警告?我的代码是否合法且没有未定义的行为(w.r.t.C ++ 03标准)?我应该在编译单元中将CompareIndex
设为全局struct
吗?
当然,这是对C字符串数组进行排序的愚蠢方法。
真正的代码有点不同。实际上,我正在尝试在MELT插件中使用std::stable_sort
(一种特定于域的语言来扩展和自定义GCC)。 MELT正在生成C ++代码并且具有复制 garbage collector(因此指针由GC移动)。因此,我需要使用索引数组进行排序:compare函数实际上调用了一个MELT闭包(它可以在任意时刻触发复制GC),因此我需要按索引排序(而不是按原始指针排序)。我希望保持MELT生成的C ++代码符合编译GCC所需的C ++标准(03或98)。
感谢juanchopanza's answer我通过在CompareIndex
之前移动全球范围内的mysort
声明解决了这个问题。
我刚刚承诺了海湾合作委员会MELT分会的svn修订版206748;它的文件gcc/melt/warmelt-base.melt
现在包含multiple_sort_new
MELT函数(在multiple_sort
运行良好时使用std::stable_sort
)和生成的全局Melt_Sort_Compare_Index
类C ++代码。
答案 0 :(得分:5)
在C ++ 03中不允许使用本地类型作为模板参数。
来自ISO / IEC 14882, 14.3.1模板类型参数[temp.arg.type] :
本地类型,没有链接的类型,未命名的类型或类型 任何这些类型的复合不得用作 模板类型参数的模板参数。
给出的例子如下:
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
}
此限制已在C ++ 11中解除。