Класс C ++ для бокса и распаковки - PullRequest
2 голосов
/ 27 октября 2019

Я хочу иметь класс Boxed_value, который может InBox других типов (начиная с int, double, string ...), аналогично object в C#. Этот тип класса может быть далее передан функциям, которые Unbox it. Эти функции получат ссылку:

void receiver( Boxed_value & bv ) {}

Итак, это не должен быть шаблон. Или же? Мне нужен рецепт ... Функция UnBox может быть отдельной и шаблонной. В этом случае receiver может получить 2 параметра:

void receiver( Boxed_value & bv, Engine & eng ) {}

Реализация ниже является фиктивной и не компилируется.

struct Boxed_value {
    void inbox(int v) { _iv = v; }
    void inbox(double v) { _dv = v; }
    void inbox(std::string & v) { _sv = v; }

    int _iv;
    double _dv;
    std::string _sv;
};

struct Engine {
    template<typename T>
    T unbox(Boxed_value bv) { 
        if (std::is_same<T, typeid(bv._iv).name()>::value) { return _iv };
        if (std::is_same<T, typeid(bv._dv).name()>::value) { return _dv };
        if (std::is_same<T, typeid(bv._sv).name()>::value) { return _sv };
    }
};

1 Ответ

3 голосов
/ 27 октября 2019
  1. Обратите внимание, что во время компиляции каждый экземпляр if должен быть создан;это означает, что вы возвращаете различные типы в функции unbox.

  2. Вы должны сравнить тип членов в std::is_same, но не sth, как typeid(bv._iv).name(), который является не типом, а объектом с типом const char*.

Вы можете применить Constexpr Если (начиная с C ++ 17).

Если значение true, то оператор-ложь отбрасывается (если присутствует), в противном случае оператор-true отбрасывается.

и использует decltype (начиная с C ++ 11), чтобы получить тип членов.

например,

template<typename T>
T unbox(const Boxed_value& bv) { 
    if constexpr (std::is_same<T, decltype(bv._iv)>::value) { return bv._iv };
    else if constexpr (std::is_same<T, decltype(bv._dv)>::value) { return bv._dv };
    else if constexpr (std::is_same<T, decltype(bv._sv)>::value) { return bv._sv };
}

До C ++ 17 вы можете применить полную специализацию .

template<typename T>
T unbox(const Boxed_value& bv);

template<>
decltype(Boxed_value::_iv) unbox<decltype(Boxed_value::_iv)> (const Boxed_value& bv) { return bv._iv; }
template<>
decltype(Boxed_value::_dv) unbox<decltype(Boxed_value::_dv)> (const Boxed_value& bv) { return bv._dv; }
template<>
decltype(Boxed_value::_sv) unbox<decltype(Boxed_value::_sv)> (const Boxed_value& bv) { return bv._sv; }

PS: я изменил тип параметраот Boxed_value до const Boxed_value&, чтобы избежать ненужного копирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...