Работа с cv-модификаторами в аргументе шаблона - PullRequest
0 голосов
/ 12 июня 2019

Я пытаюсь реализовать какой-то шаблон оболочки для управления памятью:

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;
  }
};

Я ищу способ добавить вариации cv в 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 Ответ

1 голос
/ 12 июня 2019

Инверсия квалификатора типа const может быть достигнута с использованием мета-функции conditional: https://en.cppreference.com/w/cpp/types/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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...