我们被许多次被以下错误所困扰:
#include <iostream> #include <vector> #include <algorithm> using namespace std; void print(int* pn) { cout << *pn << " "; } int main() { int* n1 = new int(1); int* n2 = new int(2); int* n3 = new int(3); vector<int*> v; v.push_back(n1); v.push_back(n2); v.push_back(n3); sort(v.begin(),v.end()); // Here be dragons! for_each(v.begin(),v.end(),print); cout << endl; delete n1; delete n2; delete n3; }
问题是std :: sort是比较整数指针而不是整数,这不是程序员的意图.更糟糕的是,输出可能显示正确和确定(考虑新的或在堆栈上分配的地址的顺序).根本的问题是,最终调用operator<对于T,当T是指针类型时,这很少是一个好主意. 有什么办法可以防止这种或至少得到一个编译器警告?例如,有没有办法创建一个自定义版本的std :: sort,当T是一个指针时需要比较功能?
解决方法
对于一般的指针,您可以这样做:
#include <ctime> #include <vector> #include <cstdlib> #include <algorithm> #include <functional> #include <type_traits> namespace util { struct sort_pointers { bool operator() ( int *a,int *b ) { return *a < *b; } }; template <typename T,bool is_pointer = !std::tr1::is_pointer<T>::value> struct sort_helper { typedef std::less<T> wont_compare_pointers; }; template <typename T> struct sort_helper<T,false> { }; template <typename Iterator> void sort( Iterator start,Iterator end ) { std::sort( start,end,sort_helper < typename Iterator::value_type >::wont_compare_pointers() ); } template <typename Iterator,class Func> void sort( Iterator start,Iterator end,Func f ) { std::sort( start,f ); } } int main() { std::vector<int> v1; std::vector<int*> v2; srand(time(0)); for( int i = 0; i < 10; ++i ) { v1.push_back(rand()); } util::sort( v1.begin(),v1.end() ); for( int i = 0; i < 10; ++i ) { v2.push_back(&v1[i]); } /* util::sort( v2.begin(),v2.end() ); */ //fails. util::sort( v2.begin(),v2.end(),util::sort_pointers() ); return 0; }
std :: tr1 :: is_pointer只是在Visual Studio 2008中调用的,但是我认为Boost也有一个,而较新的编译器可能会将它提供为std :: is_pointer.我相信有人能够写一个更漂亮的解决方案,但这似乎是有效的.
但我必须说,我同意齿轮,没有理由,程序员应该能够看到这将是一个问题,并采取相应的行动.
加成:
您可以将其概括一点,我想,要自动选择一个函数,将取消引用指针并比较值:
namespace util { template <typename T> struct sort_pointers { bool operator() ( T a,T b ) { return *a < *b; } }; template <typename T,bool is_pointer = !std::tr1::is_pointer<T>::value> struct sort_helper { typedef std::less<T> compare; }; template <typename T> struct sort_helper<T,false> { typedef sort_pointers<T> compare; }; template <typename Iterator> void sort( Iterator start,Iterator end ) { std::sort( start,sort_helper < typename Iterator::value_type >::compare() ); } }
这样你不必考虑如果你提供它与指针比较与否,它将自动被整理出来.