आलूस्वाटर के जवाब से प्रेरित, मैंने अपना दिन सी ++ 14 के लिए मानक लेआउट टुपल बनाने के लिए समर्पित किया है।
कोड वास्तव में काम करता है, लेकिन वर्तमान में उपयोग के लिए उपयुक्त नहीं है क्योंकि इसमें अपरिभाषित व्यवहार शामिल है। इसे सबूत-अवधारणा के रूप में समझें। यहाँ कोड मैं के साथ समाप्त हो गया है:
#include <iostream>
#include <type_traits>
#include <array>
#include <utility>
#include <tuple>
//get_size
template <typename T_head>
constexpr size_t get_size()
{
return sizeof(T_head);
}
template <typename T_head, typename T_second, typename... T_tail>
constexpr size_t get_size()
{
return get_size<T_head>() + get_size<T_second, T_tail...>();
}
//concat
template<size_t N1, size_t... I1, size_t N2, size_t... I2>
constexpr std::array<size_t, N1+N2> concat(const std::array<size_t, N1>& a1, const std::array<size_t, N2>& a2, std::index_sequence<I1...>, std::index_sequence<I2...>)
{
return { a1[I1]..., a2[I2]... };
}
template<size_t N1, size_t N2>
constexpr std::array<size_t, N1+N2> concat(const std::array<size_t, N1>& a1, const std::array<size_t, N2>& a2)
{
return concat(a1, a2, std::make_index_sequence<N1>{}, std::make_index_sequence<N2>{});
}
//make_index_array
template<size_t T_offset, typename T_head>
constexpr std::array<size_t, 1> make_index_array()
{
return {T_offset};
}
template<size_t T_offset, typename T_head, typename T_Second, typename... T_tail>
constexpr std::array<size_t, (sizeof...(T_tail) + 2)> make_index_array()
{
return concat(
make_index_array<T_offset, T_head>(),
make_index_array<T_offset + sizeof(T_head),T_Second, T_tail...>()
);
}
template<typename... T_args>
constexpr std::array<size_t, (sizeof...(T_args))> make_index_array()
{
return make_index_array<0, T_args...>();
}
template<int N, typename... Ts>
using T_param = typename std::tuple_element<N, std::tuple<Ts...>>::type;
template <typename... T_args>
struct standard_layout_tuple
{
static constexpr std::array<size_t, sizeof...(T_args)> index_array = make_index_array<T_args...>();
char storage[get_size<T_args...>()];
//Initialization
template<size_t T_index, typename T_val>
void initialize(T_val&& val)
{
void* place = &this->storage[index_array[T_index]];
new(place) T_val(std::forward<T_val>(val));
}
template<size_t T_index, typename T_val, typename T_val2, typename... T_vals_rest>
void initialize(T_val&& val, T_val2&& val2, T_vals_rest&&... vals_rest)
{
initialize<T_index, T_val>(std::forward<T_val>(val));
initialize<T_index+1, T_val2, T_vals_rest...>(std::forward<T_val2>(val2), std::forward<T_vals_rest>(vals_rest)...);
}
void initialize(T_args&&... args)
{
initialize<0, T_args...>(std::forward<T_args>(args)...);
}
standard_layout_tuple(T_args&&... args)
{
initialize(std::forward<T_args>(args)...);
}
//Destruction
template<size_t T_index, typename T_val>
void destroy()
{
T_val* place = reinterpret_cast<T_val*>(&this->storage[index_array[T_index]]);
place->~T_val();
}
template<size_t T_index, typename T_val, typename T_val2, typename... T_vals_rest>
void destroy()
{
destroy<T_index, T_val>();
destroy<T_index+1, T_val2, T_vals_rest...>();
}
void destroy()
{
destroy<0, T_args...>();
}
~standard_layout_tuple()
{
destroy();
}
template<size_t T_index>
void set(T_param<T_index, T_args...>&& data)
{
T_param<T_index, T_args...>* ptr = reinterpret_cast<T_param<T_index, T_args...>*>(&this->storage[index_array[T_index]]);
*ptr = std::forward<T_param<T_index, T_args...>>(data);
}
template<size_t T_index>
T_param<T_index, T_args...>& get()
{
return *reinterpret_cast<T_param<T_index, T_args...>*>(&this->storage[index_array[T_index]]);
}
};
int main() {
standard_layout_tuple<float, double, int, double> sltuple{5.5f, 3.4, 7, 1.22};
sltuple.set<2>(47);
std::cout << sltuple.get<0>() << std::endl;
std::cout << sltuple.get<1>() << std::endl;
std::cout << sltuple.get<2>() << std::endl;
std::cout << sltuple.get<3>() << std::endl;
std::cout << "is standard layout:" << std::endl;
std::cout << std::boolalpha << std::is_standard_layout<standard_layout_tuple<float, double, int, double>>::value << std::endl;
return 0;
}
लाइव उदाहरण:
यह नहीं के रूप में है उपयोग के लिए उपयुक्त अभी तक है, वास्तव में केवल इसका इलाज करें इस राज्य में एक सबूत-अवधारणा के रूप में। मैं शायद इन मुद्दों में से कुछ पर सुधार करने के लिए वापस आऊंगा।या, यदि कोई और इसे सुधार सकता है, तो संपादित करने के लिए स्वतंत्र महसूस करें।
यदि आप इसे जानना चाहते हैं क्योंकि आप अनुकूलन अवसर चाहते हैं, तो आपको 'std :: is_standard_layout' का उपयोग करना चाहिए और संकलन-समय शाखा लेनी चाहिए। फिर आप यह जानकर आराम कर सकते हैं कि आप स्वयं के प्रकार के सभी विवरणों को जानने के बिना इष्टतम हैं। – GManNickG
ऐसा लगता है कि ऐसा होगा, लेकिन मुझे मानक के अनुभाग में 'मानक लेआउट' का कोई उल्लेख नहीं मिल रहा है जिसमें 'tuple' शामिल है। कहीं और उल्लेख हो सकता है, लेकिन यदि ऐसा है तो मुझे अभी तक यह नहीं मिला है। –