std :: sort与本地类型比较

时间:2014-01-18 08:09:24

标签: c++ gcc

以下示例

// 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++ -vgcc 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 ++代码。

1 个答案:

答案 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中解除。