如何在类型 T 的模板类中有条件地实现函数,其中 T 是指向类型 S 的指针,仅当类型 S 具有运算符时<?

问题描述 投票:0回答:1

我有一个容器模板类,它内部聚合了类型为

std::vector
T
,其中
T
实际上是指向
S
类型的指针。我想创建一个成员函数
insert_sorted()
,只有当
S
T
指向的类型实际上支持
operator<()
时才会实现该函数。

可悲的是,除了基本的东西之外,我不太熟悉模板,而且类型特征对我来说也是一个未知的国家。我一直在 SO 和互联网上其他地方查看许多类似的问题,但我太笨了,无法找出正确的语法。看来我需要使用

std::enable_if
,但是如何呢?理想情况下,我希望将声明和实现分开。有人可以帮忙吗?顺便说一句,我正在 C++17 中使用 MSVC 2022。

这是类的声明(删除了一些不必要的东西)。除了

insert_sorted()
之外的所有内容都可以编译并运行:

#include <vector>
#include <algorithm>
#include <type_traits>
#include <utility>
#include <assert.h>


// Disable warning 'C4251': class 'type1' needs to have dll-interface to be used by clients of class 'type2'
// Disable warning 'C4275': non dll-interface class used as base for dll-interface class
#pragma warning(disable:4251 4275)


namespace supports
{
  namespace details { struct return_t {}; }

  template<typename T>
  details::return_t operator<(T const&, T const&);

  template<typename T>
  struct less_than : std::integral_constant<bool,
    !std::is_same<decltype(std::declval<std::remove_pointer<T> const&>() < std::declval<std::remove_pointer<T> const&>()), details::return_t>::value>
  {};

  template<typename T>
  struct greater_than : std::integral_constant<bool,
    !std::is_same<decltype(std::declval<T const&>() > std::declval<T const&>()), details::return_t>::value>
  {};

  template<typename T>
  struct equal : std::integral_constant<bool,
    !std::is_same<decltype(std::declval<T const&>() == std::declval<T const&>()), details::return_t>::value>
  {};

  template<typename T>
  struct not_equal : std::integral_constant<bool,
    !std::is_same<decltype(std::declval<T const&>() != std::declval<T const&>()), details::return_t>::value>
  {};
}


// PtrVector
template<typename T>
class PtrVector
{
public:
  typedef typename std::vector<T>::value_type value_type;
  typedef typename std::vector<T>::size_type size_type;
  typedef typename std::vector<T>::reference reference;
  typedef typename std::vector<T>::const_reference const_reference;
  typedef typename std::vector<T>::pointer pointer;
  typedef typename std::vector<T>::const_pointer const_pointer;
  typedef typename std::vector<T>::iterator iterator;
  typedef typename std::vector<T>::const_iterator const_iterator;
  typedef typename std::vector<T>::reverse_iterator reverse_iterator;
  typedef typename std::vector<T>::const_reverse_iterator const_reverse_iterator;

  PtrVector(bool owner = true, size_type reserve = 0);

  iterator                  begin();
  const_iterator            begin() const;
  iterator                  end();
  const_iterator            end() const;


  bool                      insert_sorted(const value_type& val, typename std::enable_if_t<supports::less_than<T>::value, int> = 0);

protected:
  std::vector<T> m_container;
};


// PtrVector implementation
template<typename T>
bool PtrVector<T>::insert_sorted(const value_type& val, typename std::enable_if_t<supports::less_than<T>::value, int>)
{
  auto it = std::lower_bound(begin(), end(), val, [](const value_type& a, const value_type& b)->bool { return *a < *b; });

  if (it == end() || *val < *(*it))
  {
    m_container.insert(it, val);
    return true;
  }
  return false;
}

我现在找到了一个可行的解决方案,其中成员函数在类声明中实现。但是,我似乎无法将代码分为声明和实现。说实话,没有必要,但这样会更好看。

  template <typename = std::enable_if_t<supports::less_than<T>, int>>
  bool insert_sorted(const value_type& val)
  {
    auto it = std::lower_bound(begin(), end(), val, [](const value_type& a, const value_type& b)->bool { return *a < *b; });

    if (it == end() || *val < *(*it))
    {
      m_container.insert(it, val);
      return true;
    }
    return false;
  }

理想情况下,我想要这样的东西,但实现被标记为错误(声明不匹配):

  template<typename = std::enable_if_t<supports::less_than<T>, int>>
  bool                      insert_sorted(const value_type& val);
template<typename T, typename = std::enable_if_t<supports::less_than<T>, int>>
bool PtrVector<T>::insert_sorted(const value_type& val)
{
  auto it = std::lower_bound(begin(), end(), val, [](const value_type& a, const value_type& b)->bool { return *a < *b; });

  if (it == end() || *val < *(*it))
  {
    m_container.insert(it, val);
    return true;
  }
  return false;
}
c++ c++11 templates c++17 type-traits
1个回答
0
投票

因为

insert_sorted()
是一个嵌套模板,所以你需要2个
template
来实现它,例如:

template<typename T>
template<typename = std::enable_if_t<supports::less_than<T>, int>>
bool PtrVector<T>::insert_sorted(const value_type& val)
{
  auto it = std::lower_bound(begin(), end(), val, [](const value_type& a, const value_type& b)->bool { return *a < *b; });

  if (it == end() || *val < *(*it))
  {
    m_container.insert(it, val);
    return true;
  }
  return false;
}

在线演示

© www.soinside.com 2019 - 2024. All rights reserved.