Created
August 13, 2015 21:46
-
-
Save Manu343726/aed8fbefa586c5b6a0e8 to your computer and use it in GitHub Desktop.
c++ customizable tuple
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "tuple.hpp" | |
#include <iostream> | |
template<typename T> | |
std::intptr_t between(const T& lhs, const T& rhs) | |
{ | |
return reinterpret_cast<std::intptr_t>(&lhs) - reinterpret_cast<std::intptr_t>(&rhs); | |
} | |
template<typename T> | |
std::intptr_t between(const T* lhs, const T* rhs) | |
{ | |
return reinterpret_cast<std::intptr_t>(lhs) - reinterpret_cast<std::intptr_t>(rhs); | |
} | |
template<typename T, typename U, typename = std::enable_if_t<!std::is_pointer<T>::value && !std::is_pointer<U>::value>> | |
std::intptr_t between(const T& lhs, const U& rhs) | |
{ | |
return reinterpret_cast<std::intptr_t>(&lhs) - reinterpret_cast<std::intptr_t>(&rhs); | |
} | |
template<typename T, typename U> | |
std::intptr_t between(const T* lhs, const U* rhs) | |
{ | |
return reinterpret_cast<std::intptr_t>(lhs) - reinterpret_cast<std::intptr_t>(rhs); | |
} | |
struct foo | |
{ | |
int i, j, k; | |
}; | |
int main() | |
{ | |
auto tuple = ctti::make_interleaved_storage<400,-400,400>(1, 2, 3); | |
foo f; | |
auto* tuple_addr = &tuple; | |
auto* first = &std::get<0>(tuple); | |
auto* second = &std::get<1>(tuple); | |
auto* third = &std::get<2>(tuple); | |
std::cout << "sizeof(int): " << sizeof(int) << "\n"; | |
std::cout << "sizeof(tuple): " << sizeof(decltype(tuple)) << "\n"; | |
std::cout << "sizeof(struct): " << sizeof(decltype(f)) << "\n"; | |
std::cout << "sizeof(tuple_slot<int,0>): " << sizeof(ctti::detail::tuple_slot<int,0>) << "\n"; | |
std::cout << "tuple: " << tuple_addr << "\n"; | |
std::cout << first << "\n"; | |
std::cout << second << "\n"; | |
std::cout << third << "\n"; | |
std::cout << "struct: " << &f << "\n"; | |
std::cout << &f.i << "\n"; | |
std::cout << &f.j << "\n"; | |
std::cout << &f.k << "\n"; | |
std::cout << between(third, &tuple) << "\n"; | |
std::cout << between(second, third) << "\n"; | |
std::cout << between(first, second) << "\n"; | |
std::cin.get(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <cstddef> | |
#include <tuple> | |
namespace ctti | |
{ | |
template<std::size_t Padding> | |
struct pad | |
{ | |
char padding[Padding]; | |
}; | |
template<> | |
struct pad<0> | |
{}; | |
template<typename T, int Padding> | |
struct slot {}; | |
namespace detail | |
{ | |
template<typename T, int Padding, bool positive = (Padding > 0)> | |
struct tuple_slot | |
{ | |
using elem_type = T; | |
template<typename... Args> | |
tuple_slot(Args&&... args) : | |
elem{std::forward<Args>(args)...} | |
{} | |
T elem; | |
const volatile char padding[Padding] = {0}; | |
static constexpr int padding_bytes = Padding; | |
}; | |
template<typename T, int Padding> | |
struct tuple_slot<T, Padding, false> | |
{ | |
using elem_type = T; | |
template<typename... Args> | |
tuple_slot(Args&&... args) : | |
elem{ std::forward<Args>(args)... } | |
{} | |
const volatile char padding[-Padding] = {0}; | |
T elem; | |
static constexpr int padding_bytes = Padding; | |
}; | |
template<typename T> | |
struct tuple_slot<T, 0, false> | |
{ | |
using elem_type = T; | |
template<typename... Args> | |
tuple_slot(Args&&... args) : | |
elem{ std::forward<Args>(args)... } | |
{} | |
T elem; | |
static constexpr int padding_bytes = 0; | |
}; | |
template<typename T, int Padding> | |
const T& get(const ctti::detail::tuple_slot<T,Padding>& pair) | |
{ | |
return pair.elem; | |
} | |
template<typename T, int Padding> | |
T& get(ctti::detail::tuple_slot<T, Padding>& pair) | |
{ | |
return pair.elem; | |
} | |
template<typename T, int Padding> | |
T&& get(ctti::detail::tuple_slot<T, Padding>&& pair) | |
{ | |
return pair.elem; | |
} | |
} | |
template<typename... Slots> | |
struct interleaved_storage; | |
template<typename... Ts, int... Paddings> | |
struct interleaved_storage<slot<Ts,Paddings>...> : std::tuple<ctti::detail::tuple_slot<Ts, Paddings>...> | |
{ | |
using base_t = std::tuple<ctti::detail::tuple_slot<Ts, Paddings>...>; | |
template<typename... Args> | |
explicit interleaved_storage(Args&&... args) : | |
base_t{ ctti::detail::tuple_slot<Args, Paddings>{std::forward<Args>(args)}... } | |
{} | |
}; | |
template<int... Paddings, typename... Ts> | |
interleaved_storage<slot<std::decay_t<Ts>,Paddings>...> make_interleaved_storage(Ts&&... args) | |
{ | |
return interleaved_storage<slot<std::decay_t<Ts>, Paddings>...>( std::forward<Ts>(args)... ); | |
} | |
} | |
namespace std | |
{ | |
template<std::size_t Idx, typename... Ts, std::size_t... Paddings> | |
struct tuple_element<Idx, ctti::interleaved_storage<ctti::slot<Ts,Paddings>...>> | |
{ | |
using type = typename std::tuple_element<Idx, std::tuple<std::pair<Ts, ctti::pad<Paddings>>...>>::type::first_type; | |
}; | |
template<std::size_t Idx, typename... Ts, std::size_t... Paddings> | |
constexpr std::tuple_element_t<Idx, std::tuple<Ts...>> get(const ctti::interleaved_storage<ctti::slot<Ts, Paddings>...>& tuple) | |
{ | |
return std::get<Idx>(static_cast<std::tuple<std::pair<Ts, ctti::pad<Paddings>>...>&>(tuple)).first; | |
} | |
template<std::size_t Idx, typename... Ts, std::size_t... Paddings> | |
constexpr std::tuple_element_t<Idx, std::tuple<Ts...>>& get(ctti::interleaved_storage<ctti::slot<Ts, Paddings>...>& tuple) | |
{ | |
return std::get<Idx>(static_cast<std::tuple<std::pair<Ts, ctti::pad<Paddings>>...>&>(tuple)).first; | |
} | |
template<std::size_t Idx, typename... Ts, std::size_t... Paddings> | |
constexpr std::tuple_element_t<Idx, std::tuple<Ts...>>&& get(ctti::interleaved_storage<ctti::slot<Ts, Paddings>...>&& tuple) | |
{ | |
return std::get<Idx>(static_cast<std::tuple<std::pair<Ts, ctti::pad<Paddings>>...>&&>(std::move(tuple))).first; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment