专业化更少<>更大<>

specializing less<> and greater<>

本文关键字:gt lt 更大 专业化      更新时间:2023-10-16

我正试图实现一个AVL-List-Container,并希望给程序员通过模板传递一个参数到容器的可能性,以影响排序顺序。

STL容器(set, sort等)允许使用带重载()操作符的结构体less<>greater<>作为参数。我没有设法将函子传递给容器。

测试场景为:

#include <iostream>
#include <functional>
using namespace std;
namespace TEST_SPACE {
template< typename T, typename COMP_FUNC = ::std::less<T> >
class cTst {
  T data;
  T* data_ptr;
public:
  template< typename U = T >
  bool get_min_00( ) { }
  template< typename V,  typename FUNC = COMP_FUNC, bool dummy = false>
  bool get_min_01( V a, V b  ) {
  return (*FUNC) ( a, b );
  }
};  // class cTst
}   // namespace TEST_SPACE
int main() {
TEST_SPACE::cTst< int > obj_00;
obj_00.get_min_00< int >();     // working
obj_00.get_min_01< int > ( 2, 3 );  // working
obj_00.get_min_01< int,  ::std::greater<int>() > ( 2, 3 );
return 0;
}

我使用gcc版本4.9.2 (Debian 4.9.2-10)。编译器报错:

gcc -Wall -c -O2 -std=c++11 -fpic _tst-04.cpp 
_tst-04.cpp: In member function ‘bool TEST_SPACE::cTst<T, COMP_FUNC>::get_min_01(V, V)’:
_tst-04.cpp:31:20: error: expected primary-expression before ‘)’ token
  return (*FUNC) ( a, b );
        ^
_tst-04.cpp: In instantiation of ‘bool TEST_SPACE::cTst<T, COMP_FUNC>::get_min_01(V, V) [with V = int; FUNC = std::less<int>; bool dummy = false; T = int; COMP_FUNC = std::less<int>]’:
_tst-04.cpp:62:37:   required from here    

我搜索了网络,没有找到合适的/有效的解决这个问题的方法。什么好主意吗?

模板的形参必须是"typename COMP_FUNC",类型/类。

obj_00.get_min_01< int,  ::std::greater<int>() > ( 2, 3 );

"::std::greater()"在这里不是类型,而是构造函数调用。这应该是:

obj_00.get_min_01< int,  ::std::greater<int> > ( 2, 3 );

我找到了一个临时解决方案:

#include <iostream>
#include <functional>
#include <string>
using namespace std;

template <typename T, typename CMP = std::less<T>, typename A1, typename A2>
bool getOrder_05( const A1&& a, const A2&& b, CMP func =  CMP( ) )
{
  return (func)( std::forward<A1>(a), std::forward<A2>(b) );
  //return new T(std::forward<A1>(a1), std::forward<A2>(a2));
}
class cStructure {
public:
cStructure( int x, std::string str = "" ) : m_int_value( x ) , m_str_value( str ) {}
friend std::less<cStructure >;
friend std::greater<cStructure >;
friend std::less<cStructure * >;
int GetIntValue() { return this->m_int_value; } ;
std::string GetStringValue() { return this->m_str_value; } ;
protected:
int m_int_value = 0;
std::string m_str_value;

};  // cStructure
namespace std {
template<>
struct less<cStructure> : public binary_function <cStructure , cStructure , bool>
{
public:
    bool operator()(const cStructure &a, const cStructure & b ) const
    {
    return a.m_int_value < b.m_int_value ;
    }
};
}
namespace std {
template<>
struct greater<cStructure> : public binary_function <cStructure , cStructure , bool>
{
public:
    bool operator()(const cStructure &a, const cStructure & b ) const
    {
    return a.m_int_value > b.m_int_value ;
    }
};
}
namespace std {
template<>
struct less<cStructure *> : public binary_function <cStructure *, cStructure *, bool>
{
public:
    bool operator()(const cStructure * a, const cStructure * b ) const
    {
    return a->m_int_value < b->m_int_value ;
    }

};  // less<cStructure *>
}
namespace std {
class lessByStringValue : public binary_function < cStructure, cStructure, bool >
{
public:
    bool operator()( cStructure * a, cStructure  * b ) const
    {
    return a->GetStringValue( ) < b->GetStringValue( ) ;
    }
};  // lessByStringValue<cStructure *>
}

int main()
{
  int set_value_00 = 20;
cStructure obj_00 = cStructure( 11, "Pizza Mare" );
cStructure obj_01 = cStructure(  7, "Ciabatta" );
cStructure *obj_02 = new cStructure( 14, "Pizza Margeritha");
cStructure *obj_03 = new cStructure(  8, "Cannelloni");
cStructure *obj_04 = new cStructure(  5, "Spagetthi");
cStructure *obj_05 = new cStructure( 10, "Pizza Napoli" );
cStructure *obj_06 = new cStructure( 12, "Pizza Funghi" );
bool value_05a = getOrder_05<cStructure>( obj_00, obj_01 );
bool value_05b = getOrder_05<cStructure * >( obj_02, obj_03 );
bool value_05c = getOrder_05<cStructure * >( &obj_00, obj_03 );
bool value_05d = getOrder_05<int>( 2, int(15) );
bool value_05e = getOrder_05<int, std::less<int> >( 2, int(15) );
bool value_05f = getOrder_05<cStructure *, std::less<cStructure *> >( &obj_00, obj_03 );
bool value_05g = getOrder_05<cStructure *, std::lessByStringValue >( &obj_00, obj_03 );

delete obj_02;
delete obj_03;
delete obj_04;
delete obj_05;
delete obj_06;

return 1;
}

这是一个临时解决方案,因为它不完全是我想要的:模板

template <typename T, typename CMP = std::less<T>, typename A1, typename A2>
bool getOrder_05( const A1&& a, const A2&& b, CMP func =  CMP( ) )
{
  return (func)( std::forward<A1>(a), std::forward<A2>(b) );
  //return new T(std::forward<A1>(a1), std::forward<A2>(a2));
}

需要类型的地址,而不是()操作符的地址。因此我必须写

bool value_05f = getOrder_05<cStructure *, std::less<cStructure *> >( &obj_00, obj_03 );
bool value_05g = getOrder_05<cStructure *, std::lessByStringValue >( &obj_00, obj_03 );
不是

bool value_05f = getOrder_05<cStructure *, std::less<cStructure *>() >( &obj_00, obj_03 );
bool value_05g = getOrder_05<cStructure *, std::lessByStringValue() >( &obj_00, obj_03 );
也许有人知道另一种方法?