Использование шаблонов для определения того, являются ли члены класса константными - PullRequest
4 голосов
/ 26 мая 2020

У меня есть шаблонный класс, и я хотел бы почти переключить, являются ли элементы в нем константными на основе типа шаблона.

псевдокод:

template<bool isConst>
Class ConstableClass
{
public:
    // if isConst == true make this method const
    void DoSomething() "const";

    // if isConst == true make the returned smartpointer type const method const
    std::unique_ptr<"const" int> operator->() "const";

private:
    // if isConst == true add const at the start of the next line
    "const" int foo;
}

Это что-то вроде возможно?

Ответы [ 4 ]

2 голосов
/ 27 мая 2020

С типажами и SFINAE:

template <bool isConst>
class ConstableClass
{
public:
    template <bool C = isConst, typename = std::enable_if_t<C>>
    void DoSomething() const;

    template <bool C = isConst, typename = std::enable_if_t<!C>>
    void DoSomething();

    template <bool C = isConst, typename = std::enable_if_t<C>>
    std::unique_ptr<const int> operator->();

    template <bool C = isConst, typename = std::enable_if_t<!C>>
    std::unique_ptr<int> operator->();

private:
    std::conditional_t<isConst, const int, int> foo{};
};

Со специализацией:

template <bool isConst>
class ConstableClass
{
public:
    void DoSomething() const;

    std::unique_ptr<const int> operator->() const;

protected:
    const int foo{};
};

template <>
class ConstableClass<false>
{
public:
    void DoSomething();

    std::unique_ptr<int> operator->();

protected:
    int foo{};
};

С ограничениями в :

template <bool isConst>
class ConstableClass
{
public:
    void DoSomething() const requires isConst;

    void DoSomething() requires not isConst;

    std::unique_ptr<const int> operator->() const requires isConst;

    std::unique_ptr<int> operator->() requires not isConst;

private:
    std::conditional_t<isConst, const int, int> foo{};
};
1 голос
/ 26 мая 2020

Первый вариант использования невозможен. Вы не можете сделать модификаторы функций условными и основанными на каком-то шаблоне. Однако я полагаю, что вы пытаетесь это сделать, потому что не хотите копировать и вставлять код между const и обычной версией функции. В этом случае просто напишите метод private impl, который выполняет фактическую работу, и используйте его в cost и не const версии класса.

private:
int& get_impl() const {...}
public:
const int& get() const {return get_impl();}
int& get() {return get_impl();}

Остальное возможно и довольно просто:

std::unique_ptr<"const" int>
// we can do this by:
std::unique_ptr<std::conditional_t<isConst, const int, int>> ...

// this can be written more elegantly as
template <typename T, bool isConst>
using const_if_t = std::conditional_t<isConst, const T, T>;

std::unique_ptr<const_if_t<int, isConst>>;

Создание переменных-членов const по условию было бы довольно бессмысленным, потому что это уже происходит, когда вы в любом случае создаете переменную const.

0 голосов
/ 27 мая 2020

У меня есть шаблонный класс, и я хотел бы почти переключить, являются ли элементы в нем константными в зависимости от типа шаблона. Возможны ли такие вещи?

Да, и я считаю, что специализации более читабельны (если у вас нет доступа к концепциям). В приведенном ниже примере довольно четко показаны два случая.

template<bool isConst>
class ConstableClass;

template<>
class ConstableClass<false>
{
  int foo;
public:
  void DoSomething();
  std::unique_ptr<int> operator->();
};

template<>
class ConstableClass<true>
{
  int const foo;
public:
  ConstableClass()
    : foo{0} {} // example
  void DoSomething() const;
  std::unique_ptr<int const> operator->() const;
};

Имейте в виду, что вам необходимо добавить конструктор для случая true, поскольку добавление const к foo неявно удаляет его.

0 голосов
/ 26 мая 2020

Нет, это невозможно сделать так, как вы хотите. Хотя есть способ манипулировать типами переменных-членов и типами возвращаемых функций, нет способа добавить / удалить спецификатор const в метод. Это означает, что вам нужно написать две отдельные специализации определения класса для истинного и ложного значений параметра шаблона.

...