处理模板参数中的 cv 修饰符

Dealing with cv-modifiers in the template argument

本文关键字:cv 参数 处理      更新时间:2023-10-16

我正在尝试实现某种用于内存管理的包装器模板:

template<typename T>
class Foo {
  T * var;
  bool cpy;
  Foo(T * inp, bool cpy): var(inp), cpy(cpy) {}
public:
  // named ctors
  static Foo<T> * newRef(T * inp){
    return new Foo(inp, false);
  }
  static Foo<T> * newCpy(const Foo<T> * foo){
    return new Foo(new T(*(foo->var)), true);
  }
  /* How to add cv variations to newCpy ? */
  ~Foo(){
    if (cpy) delete var;
  }
};

我正在寻找一种在newCpy()中添加 cv 变体的方法,例如 Foo<int>::newCpy(Foo<const int> *)Foo<const int>::newCpy(Foo<int> *) 。我的尝试如下所示:

template<typename T>
class Foo {
  using mT = typename std::remove_cv<T>::type;
  // T = const int -> mT = int
  /* ... */
  static Foo<T> * newCpy(const Foo<mT> * foo){
    return new Foo(new T(*(foo->var)), true);
  }
};

但是,由于两个原因,这不起作用:

  1. 如果T不是const,则mT将与T相同,因此两个newCpy将具有完全相同的签名。

  2. Foo<T>无权访问Foo<mT>::var

有什么办法吗?

const 类型限定符的反转可以通过使用元函数 https://en.cppreference.com/w/cpp/types/conditional conditional

来实现:

下面的代码需要 C++17,但是,要转换为 C++14,只需将出现的 _v 替换为 ::value 即可。

template <typename T>
using invert_const =
    std::conditional_t<std::is_const_v<T>, std::remove_const_t<T>, const T>;

对于这个特定问题,示例用例将是

static Foo<T> * newCpy(const Foo<invert_const<T>> * foo) {
    return new Foo(new T(*(foo->var)), true);
}

在您给出的示例中,不清楚您是否打算删除易失性限定符,但是,如果我只是误解了预期的用例,则可能会发生类似的反转:

template <typename T>
using invert_volatile =
    std::conditional_t<std::is_volatile_v<T>, std::remove_volatile_t<T>, volatile T>;

这些也可以组成

template <typename T>
using invert_cv = invert_volatile<invert_const<T>>;

然后可以通过以下方式使用元函数invert_cv

static Foo<T> * newCpy(const Foo<invert_cv<T>> * foo) {
    return new Foo(new T(*(foo->var)), true);
}