c_cpp c ++可定制的元组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp c ++可定制的元组相关的知识,希望对你有一定的参考价值。

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

以上是关于c_cpp c ++可定制的元组的主要内容,如果未能解决你的问题,请参考以下文章

元组拆包具名元祖

对本身位于元组中的元组(可迭代的可迭代)求和的最有效方法是啥?

c_cpp C ++中的通用容器可迭代数组类

c_cpp 这使得整数的可打印范围为32-126(C)

如何从一个可迭代的元组中填充两个(或更多)numpy 数组?

c_cpp 可评估语言的第一个原型