C — наследование std::tuple от чего-то, добавляющего к нему виртуальные функции

#c #c 11

#c #c 11

Вопрос:

Во-первых, возможно ли наследовать std::tuple от чего-либо?

У меня есть

 std::tuple<A, B> // (common base event data)

std::tuple<C, D, E> someObj;
  

Поэтому, если я создам второй кортеж, также должен быть задействован первый базовый класс (или что-то в этом роде).

Во-вторых, и я полагаю, что более важно, во время выполнения я хочу выбрать правильную виртуальную функцию на основе моего типа.

Так, например, если

 std::tuple<A,B> { virtual void Serialize(); }
  

Я хотел бы иметь возможность использовать специальный метод Specialize дочернего класса, но с использованием шаблонов, чтобы его можно было расширить во время компиляции, но я могу выбрать метод во время выполнения.

Я подумываю о том, чтобы по-другому структурировать проблему в коде, чтобы я мог достичь этого, но если нет, мне придется прибегнуть к написанному вручную шаблонному коду для каждого кортежа.

Комментарии:

1. Нет, a std::tuple не может наследовать от какого-либо другого класса или какого-либо другого кортежа. И ваш второй пример вообще не имеет смысла. У кортежей нет виртуальных методов.

2. Вероятно, вам лучше просто писать классы для хранения ваших данных. Почему вы хотите использовать std::tuple ?

3. Ваш пример не является кодом C . Ни один из ваших блоков кода не является допустимым кодом C . Я понимаю, вы не имели в виду, что это код на C , но остальная часть вашего сообщения недостаточно последовательна, чтобы понять, о чем вы говорите. «что-то вроде этого», «Я полагаю», «на основе моего типа», «правильный», «специальный дочерний элемент», «отличается от структуры» — много бессмыслицы или неопределенного размахивания руками. Пожалуйста, включите как можно больше реального кода. Объясните, что пошло не так. Объясните, что вы пытаетесь сделать, максимально привязав к конкретному коду, насколько это возможно. Объясните, почему вы это делаете.

Ответ №1:

Кортеж не будет волшебным образом расширять другой кортеж, который вы хотите. Вместо этого вы можете предоставить свою собственную логику:

 template<typename... Types>
using child_tuple = std::tuple<A, B, Types...>

template<typename... Args>
auto make_child_tuple(A a, B b, Argsamp;amp;... args) {
    return child_tuple<std::decay_t<Args>...>{a, b, std::forward<Args>(args)...};
}
  

если вам нужна виртуальная функция в кортеже (тьфу, не надо), вам придется вводить свои собственные структуры:

 struct Interface {
    virtual void serialize() = 0;
};

template<typename... Types>
struct poly_child_tuple: Interface, child_tuple<Types...> {
    void serialize () override { /* ... */ }
};
  

Тем не менее, я настоятельно рекомендую вам предоставить общую функцию сериализации для ваших кортежей в виде функции шаблона (пожалуйста, сделайте):

 template<typename... Types, std::size_t... S>
void serialize(std::index_sequence<S...>, const std::tuple<Types...>amp; tuple) {
    int unpack[] = {(static_cast<void>(
        [](autoamp;amp; value){
            // Do things for each `value` in `tuple`
        }(std::get<S>(tuple))
    ), 0)..., 0};
}

template<typename... Types>
void serialize(const std::tuple<Types...>amp; tuple) {
    serialize(std::index_sequence_for<Types...>{}, tuple);
}
  

Затем, с помощью этой реализации, вы можете вызвать либо непосредственно вызвать его для кортежа известных типов, либо вы можете вызвать его из виртуального метода, который вы описали в своем вопросе.

Вот пример использования:

 template<typename... Types>
struct serializable_tuple_impl : Interface {
    void serialize() override {
        ::serialize(tuple);
    }

private:
    child_tuple<Types...> tuple;
};