C ++: Как оптимизировать пустой элемент данных из стандартного шаблона класса макета? - PullRequest
3 голосов
/ 23 апреля 2019

Могу ли я иметь стандартный экземпляр макета шаблона класса с необязательным нестатическим элементом данных?«Необязательный» означает, что рассматриваемый элемент данных не должен присутствовать в некоторых экземплярах класса шаблона.

То есть, учитывая:

template <typename T>
struct Dependent
{
    T      m_defaultValue;
};

template <>
struct Dependent<double>
{
};

template <typename T>
struct MyData
{
    T*              m_data;
    Dependent<T>    m_optional;

    T LotsOfAccessorMethods() const;
};

Iхочу, чтобы макет MyData<int> был эквивалентен struct { int* x; int y; }.

И я хочу, чтобы макет MyData<double> был эквивалентен struct { double* x; }.

Проблема здесь в том, чтоРешение должно соответствовать следующим ключевым ограничениям:

  1. MyData <> должно соответствовать требованиям для стандартного класса макетов .Это означает, что все члены данных должны быть расположены в одном классе.Нельзя преобразовать необязательные элементы данных в базовый класс.

  2. MyData <> не должно быть специализированным , даже частично.В реальной задаче у него довольно много методов и полей, и повторение их во всех специализациях разрушило бы весь смысл наличия универсального шаблона.


Фон:

Я хочу передать много специальных контейнерных структур в DLL / SO, которая находится вне моего контроля.Последнее означает, что я должен предположить, что DLL могла быть написана на каком-то другом языке или, возможно, просто построена с другим компилятором.Это похоже на работу со структурами стандартного макета.

Эти контейнерные структуры имеют очень похожий набор элементов данных и функций-членов, поэтому было бы стыдно (и кошмаром обслуживания) необъедините их все в шаблон класса.

Однако некоторые этих контейнеров должны иметь дополнительные элементы данных (идентификаторы тегов, специальные значения и т. д.).Отсюда вопрос.

1 Ответ

3 голосов
/ 23 апреля 2019

Как насчет этого:

#include <type_traits>
template <typename T>
struct MyData {
    struct general_impl { T* m_data; T optional; };
    struct double_impl  { T* m_data; };

    using data_type = typename std::conditional<
        std::is_same<T, double>::value,
        double_impl,
        general_impl>::type;

    data_type data;

    T LotsOfAccessorMethods() const;
};
...