【问题标题】:Using STL algorithms (specifically std::sort) from within a templated class在模板类中使用 STL 算法(特别是 std::sort)
【发布时间】:2010-02-17 05:56:24
【问题描述】:

我已经声明了一个模板类 MyContainer,如下所示,然后创建了一个 DataType1 类型的实例。 DataType1 类提供了一个友元函数“DataSpecificComparison”,std::sort 使用它来比较 DataType1 对象。程序正确编译和排序。

然后我定义了一个名为 DataType2 的类,给它一个“DataSpecificComparison”的友元实现,并用它来创建另一个 MyContainer 实例。

我现在无法将程序编译为“C2914: 'std::sort' : cannot deduc template argument as function argument is ambiguous” 编译时报错。

开发人员如何指定 DataSpecificComparison 二元谓词采用模板类型 T* 的参数?还是有其他方法可以解决这个问题?

template <class T>
class MyContainer
{
private: 
    vector<T*> m_vMyContainerObjects;
    ....

public:
    ....
    void SortMyContainerObjects()
    {
        std::sort(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(), DataSpecificComparison)
    }
}


class DataType1
{
    ....
    friend bool DataSpecificComparison(const DataType1 * lhs, const DataType1 * rhs)
}

class DataType2
{
    ....
    friend bool DataSpecificComparison(const DataType2* lhs, const DataType2* rhs)
}

【问题讨论】:

  • 可能是因为您使用的是指针向量?只是猜测。
  • 当我只定义了MyContainer,它的友元函数“DataSpecificComparison”应用程序编译运行。正是在定义 DataType2 并创建了 MyContainer 的实例时,才发生此错误。顺便说一句——我对这个解决方案的第一次尝试涉及使用 std::sort,但没有实现用户定义的二元谓词——我只是用 DataType1 实现重载了默认的小于 (

标签: c++ templates stl sorting


【解决方案1】:

您可以使用所需类型的临时局部函数指针变量来选择DataSpecificComparison的正确重载:

void SortMyContainerObjects()
{
    typedef bool (*comparer_t)(const T*, const T*);
    comparer_t cmp = &DataSpecificComparison;
    std::sort(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(), cmp);
}

这里编译器可以推断出你想使用匹配comparer_t类型的DataSpecificComparison重载,从而解决了歧义。

【讨论】:

  • 非常好,适用于我上面描述的应用程序。
【解决方案2】:

某事已经给出了正确答案,但也有基于相同原理的直接替代方案:

void SortMyContainerObjects()
{

    std::sort(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(),
       static_cast<bool (*comparer_t)(const T*, const T*)>(&DataSpecificComparison));
}

这使用了基本相同的机制。强制转换强制在 std::sort 的模板参数推导之前发生过载解决。

【讨论】:

    【解决方案3】:
    template<typename T>
    struct DataSpecificComp : public binary_function<T, T, bool>
    {
    public:
        bool operator()(const T* lhs, const T* rhs)
        {
            return *lhs < *rhs;
        }
    };
    

    调用排序函数如下图:

    sort(vi.begin(), vi.end(), DataSpecificComp<int>());
    

    【讨论】:

      【解决方案4】:

      我更喜欢以下几行:默认情况下,它将对象与less_than 进行比较(这样您就不必记住提供一个具有有趣名称的函数),并且有一个允许给您自己的重载比较函子(同样,基于值):

      #include <vector>
      #include <algorithm>
      #include <functional>
      
      template <class T, class Func>
      struct indirect_binary_call_type: public std::binary_function<const T*, const T*, bool>
      {
          Func f;
          indirect_binary_call_type(Func f): f(f) {}
          bool operator()(const T* a, const T* b) const
          {
              return f(*a, *b); 
          } 
      };
      
      template <class T, class Func>
      indirect_binary_call_type<T, Func> indirect_binary_call(Func f)
      {
          return indirect_binary_call_type<T, Func>(f);
      }
      
      template <class T>
      class MyContainer
      {
      private: 
          std::vector<T*> m_vMyContainerObjects;
      
      public:
          void Sort()
          {
              Sort(std::less<T>());
          }
          template <class Func>
          void Sort(Func f )
          {
              std::sort(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(), indirect_binary_call<T>(f));
          }
      
      };
      
      int main()
      {
          MyContainer<int> m;
          m.Sort();
          m.Sort(std::greater<int>());
      }
      

      【讨论】:

        【解决方案5】:

        您是否尝试将 DataSpecificComparison 定义为具有一系列特化的模板并为其指定类型?

        template<T>
        bool DataSpecificComparison(const T* t1, const T* t2)
        {
            // something non compilable here
        }
        
        template<> bool DataSpecificComparison<Data1>(const Data1* t1, const Data1* t2)
        {
            // return *t1 < *t2;
        }
        
        ....
        void SortMyContainerObjects()
        {
            std::sort(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(), DataSpecificComparison<T>)
        }
        ....
        

        【讨论】:

          【解决方案6】:

          模板 DataSpecificComparison 应该可以工作。也可以专门调用合适的std::sort模板,不过有点麻烦:

          template <class T>
          class MyContainer
          {
          private: 
              vector<T*> m_vMyContainerObjects;
              typedef bool (*compsT)(T, T); 
          
          public:
              ....
              void SortMyContainerObjects()
              {
                  std::sort<std::vector<T*>::iterator, compsT>(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(), DataSpecificComparison);
              }
          }
          

          【讨论】:

          • 这个解决方案对 typedef 语句进行了一些调整: typedef bool (compsT)(const T, const T*);
          猜你喜欢
          • 2014-12-29
          • 2014-04-15
          • 1970-01-01
          • 1970-01-01
          • 2010-12-15
          • 1970-01-01
          • 1970-01-01
          • 2019-04-03
          • 1970-01-01
          相关资源
          最近更新 更多