Skip to content

Instantly share code, notes, and snippets.

@Manu343726
Created August 13, 2015 21:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Manu343726/aed8fbefa586c5b6a0e8 to your computer and use it in GitHub Desktop.
Save Manu343726/aed8fbefa586c5b6a0e8 to your computer and use it in GitHub Desktop.
c++ customizable tuple
#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();
}
#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