在template参数中处理cv-modifiers

时间:2019-06-12 00:30:13

标签: c++ templates const

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

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()中添加简历变量的方法,例如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

有什么办法解决吗?

1 个答案:

答案 0 :(得分:1)

使用元函数conditionalhttps://en.cppreference.com/w/cpp/types/conditional

可以实现const类型限定符的反转。

以下代码需要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);
}