简体   繁体   中英

C++: How do I optimize out an empty data member from a standard layout class template?

Can I have a standard layout instance of a class template with an optional non-static data member? Being "optional" means that the data member in question must not be present in certain instances of the template class.

That is, given:

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 want the layout of MyData<int> to be equivalent to struct { int* x; int y; } struct { int* x; int y; } struct { int* x; int y; } .

And I want the layout of MyData<double> to be equivalent to struct { double* x; } struct { double* x; } .

The problem here is that the solution must comply with the following key restrictions:

  1. MyData<> must meet the requirements for standard layout class . Which means that all data members should be located in one class. It is impossible to refactor optional data member(s) to a base class.

  2. MyData<> must not be specialized , not even partially. In real task it has quite some methods and fields, and repeating them in all specializations would ruin the whole point of having a generic template.


Background:

I wish to communicate a lot of special container structures to a DLL/SO which is out of my control. The latter means that I should assume that DLL could have been written is some other language, or perhaps just built with another compiler. This looks like a job for Standard Layout structures.

Those container structures have very similar set of data members and member functions, so it would be a shame (and a maintenance nightmare) not to merge them all to a class template.

However, some of those containers must have extra data members (tag ids, special values, etc). Hence the question.

How about this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM