std::tuple and standard layout

std::tuple example
std::make_tuple
c++ tuple get
std tuple default value
std get tuple
std tuple indexing
vector of tuples c++
c unpack tuple

If all of the members of std::tuple are of standard layout types, is that std::tuple itself standard layout? The presence of a user-defined copy-constructor makes it non-trivial, but I was wondering if it can still be standard layout.

A quote from the spec would be good.


No, standard layout requires that all nonstatic data members belong to either one base subobject or directly to the most derived type, and typical implementations of std::tuple implement one member per base class.

Because a member-declaration cannot be a pack expansion, in light of the above requirement, a standard layout tuple cannot have more than one member. An implementation could still sidestep the issue by storing all the tuple "members" inside one char[], and obtaining the object references by reinterpret_cast. A metaprogram would have to generate the class layout. Special member functions would have to be reimplemented. It would be quite a pain.

Regular expressions library (C++11). Atomic operations Class template std::​tuple is a fixed-size collection of heterogeneous values. It is a  A standard-layout class is a class that satisfies StandardLayoutType. The behavior is undefined if std:: remove_all_extents_t < T > is an incomplete type and not (possibly cv-qualified) void. The behavior of a program that adds specializations for is_standard_layout or is_standard_layout_v (since C++17) is undefined.


Optimizing the memory layout of std::tuple. In the last few years I have become increasingly interested in bringing higher order concepts of category theory closer  Class template std::tuple is a fixed-size collection of heterogeneous values. It is a generalization of std::pair . If ( std:: is_trivially_destructible_v < Types > &&


One reason std::tuple cannot be of standard layout, as any classes with members and base classes with members, is that the standard allows for space optimization when deriving even non-empty base classes. For example:

#include <cstdio>
#include <cstdint>

class X
{
    uint64_t a;
    uint32_t b;
};

class Y
{
    uint16_t c;
};

class XY : public X, public Y
{
    uint16_t d;
};

int main() {
    printf("sizeof(X) is %zu\n", sizeof(X));
    printf("sizeof(Y) is %zu\n", sizeof(Y));
    printf("sizeof(XY) is %zu\n", sizeof(XY));
}

Outputs:

sizeof(X) is 16
sizeof(Y) is 2
sizeof(XY) is 16

The above shows that the standard allows for class trailing padding to be used for the derived class members. Class XY has two extra uint16_t members, yet its size equals to the size of base class X.

In other words, class XY layout is the same as that of another class that has no base classes and all the members of XY ordered by address, e.g. struct XY2 { uint64_t a; uint32_t b; uint16_t c; uint16_t d; };.

What makes it non-standard layout is that the size of a derived class is not a function of sizes of base classes and derived class members.

Note that the size of a struct/class is a multiple of the alignment of one of its members with the largest alignment requirement. So that an array of objects is suitably aligned for such a member. For built-in types normally sizeof(T) == alignof(T). Hence sizeof(X) is a multiple of sizeof(uint64_t).

I am not sure whether the standard requires special treatment for struct, but with g++-5.1.1 if class is replaced with struct the above code yields different output:

sizeof(X) is 16
sizeof(Y) is 2
sizeof(XY) is 24

In other words, the trailing padding space optimization is not used when struct is involved (did not test for exact conditions).

Find out if this custom tuple type can be a substitute for std::tuple in the Standard. Run benchmarks to support a claim that a standard-layout  In his "Variadic Templates are Funadic" talk at GoingNative 2012 Andrei Alexandrescu outlines a "recursive" implementation of std::tuple.He also notes that most implementations arrange tuple members in memory in the "wrong" order, that is, std::tuple<int, double, std::string> will have a memory layout where the std::string comes first and the int comes last.


The "list" approach can be used to get standard layout tuple (the following example has some inaccuracies but demonstrates the idea):

template <class... Rest>
struct tuple;

template <class T, class... Rest>
struct tuple<T, Rest...> {
    T value;
    tuple<Rest...> next;
};

template <>
struct tuple<> {};

namespace details {
    template <size_t N>
    struct get_impl {
        template <class... Args>
        constexpr static auto process(const tuple<Args...>& t) {
            return get_impl<N - 1>::process(t.next);
        }
    };

    template <>
    struct get_impl<0> {
        template <class... Args>
        constexpr static auto process(const tuple<Args...>& t) {
            return t.value;
        }
    };
}

template <size_t N, class... Args>
constexpr auto get(const tuple<Args...>& t) {
    return details::get_impl<N>::process(t);
}

template <class... Args>
constexpr auto make_tuple(Args&&... args) {
    return tuple<Args...>{std::forward<Args>(args)...};
}

The vector elements are just the addresses of the pair objects in the map and std::pair <string, string>; // Defines a name pair using DOB = std::tuple <size_t,  For example, std:: conjunction < std:: integral_constant < int, 2 >, std:: integral_constant < int, 4 >>:: value is 4. The short-circuit instantiation differentiates conjunction from fold expressions: a fold expression like ( && Bs:: value) instantiates every B in Bs, while std:: conjunction_v < Bs > stops instantiation once the value can


For such cases, std::pair has a special 'piecewise' constructor to perform in-place It is called with a special constant, followed by two tuples (see next section) defined to avoid unwanted copying), and in particular with those of std::map  Layout-compatible POD-structs standard-layout-structs and POD-unions standard-layout-unions are described in 9.2. —end note ] 5.2 ¶7 Postfix expressions [expr.post] When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg (18.8).


The Standard Library provides a special case of tuple, a 2tuple, called std::pair. which you have probably noted when operating on elements of std::map. The type std::tuple can bundle any number of values, potentially including values of different types, into a single return object:. std::tuple<int, int, int, int> foo(int a, int b) { // or auto (C++14) return std::make_tuple(a + b, a - b, a * b, a / b); }


Tuples <tuple> std::tuple is a generalization of pair that allows any number of values to be stored (i.e., zero or more, not just two): std::tuple<Type>. It is mostly​  Standard library header <tuple> From cppreference.com < cpp‎ | header std::get (std::tuple) tuple accesses specified element (function template)