Skip to content

Instantly share code, notes, and snippets.

@plasma-effect
Last active August 29, 2015 14:27
Show Gist options
  • Save plasma-effect/9ff1443a38c8c9685f48 to your computer and use it in GitHub Desktop.
Save plasma-effect/9ff1443a38c8c9685f48 to your computer and use it in GitHub Desktop.
#pragma once
// Copyright plasma-effect 2015
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt)
#include<type_traits>
#include<utility>
namespace plasma
{
namespace integral_sequence
{
template<class Ty, Ty... Is>struct integral_sequence
{
typedef integral_sequence<Ty, Is...> type;
typedef Ty value_type;
};
template<std::size_t... Is>using index_sequence = integral_sequence<std::size_t, Is...>;
template<class... Ts>struct make_integral_sequence;
template<class Ty,Ty... Is>struct make_integral_sequence<std::integral_constant<Ty,Is>...>:integral_sequence<Ty,Is...>{};
namespace detail
{
template<class T>constexpr bool is_even(T v)
{
return v % 2 == 0;
}
template<class Ty, class Prev, Ty Next, bool IsEven>struct index_next;
template<class Ty, Ty Next, Ty... Prev>struct index_next<Ty, integral_sequence<Ty, Prev...>, Next, true> :integral_sequence<Ty, Prev..., (Prev + Next)...> {};
template<class Ty, Ty Next, Ty... Prev>struct index_next<Ty, integral_sequence<Ty, Prev...>, Next, false> :integral_sequence<Ty, Prev..., (Prev + Next)..., 2 * Next> {};
template<class Ty, Ty C, bool, bool>struct make_countup_sequence_impl :index_next<Ty, typename make_countup_sequence_impl<Ty, C / 2, true, (C / 2) == 0>::type, C / 2, is_even(C)> {};
template<class Ty, Ty C,bool F>struct make_countup_sequence_impl<Ty, C, false,F>
{
static_assert(C >= 0, R"(make_countup_sequence error: "C" in "make_countup_sequence<Ty, C>" is less than 0)");
};
template<class Ty, Ty C>struct make_countup_sequence_impl<Ty, C, true, true> :integral_sequence<Ty> {};
}
template<class Ty, Ty C>struct make_countup_sequence :detail::make_countup_sequence_impl<Ty, C, (C >= 0), C == 0> {};
template<class Ty, Ty C>using make_countup_sequence_t = typename make_countup_sequence<Ty, C>::type;
template<std::size_t C>struct make_index_countup :detail::make_countup_sequence_impl<std::size_t, C, true, C == 0> {};
template<std::size_t C>using make_index_countup_t = typename make_index_countup<C>::type;
template<class Sequence, template<class>class Functor>struct sequence_foreach;
template<class Ty, Ty... Is, template<class>class Functor>
struct sequence_foreach<integral_sequence<Ty, Is...>, Functor> :
integral_sequence<Ty, Functor<std::integral_constant<Ty, Is>>::value...> {};
namespace helper
{
template<class Ty, template<Ty>class Functor>struct make_class_functor
{
template<class T>using functor = Functor<T::value>;
};
template<template<std::size_t>class Functor>using make_index_class_functor = make_class_functor<std::size_t, Functor>;
}
}
}

#What is this index tuple idiom用のアレ

#使いかた プロジェクトのリポジトリに投げ込んだりしてincludeする

#リファレンス ##plasma::integral_sequence

###integral_sequence ####宣言

template<class Ty, Ty... Is>struct integral_sequence;

####メンバ

typedef integral_sequence<Ty, Is...> type;
typedef Ty value_type;

####What is index tuple idiom用のクラス。

###plasma::integral_sequence::index_sequence ####宣言

template<std::size_t... Is>using index_sequence = integral_sequence<std::size_t, Is...>;

###make_integral_sequence ####宣言

template<class... Ts>struct make_integral_sequence;

####What is std::integral_constant列からintegral_sequenceを生成する。 #####例

using type = plasma::integral_sequence::make_integral_sequence<
	std::integral_constant<int,1>,
	std::integral_constant<int,2>,
	std::integral_constant<int,3>>;

###make_countup_sequence ####宣言

template<class Ty, Ty C>struct make_countup_sequence;
template<class Ty, Ty C>using make_countup_sequence_t =
	 typename make_countup_sequence<Ty, C>::type;

####What is 0,...C-1を含むintegral_sequenceを生成する。C==0なら空のintegral_sequenceを生成する。 ####template引数の要件 Cは0以上でなければならない。 ###make_index_countup ####宣言

template<std::size_t C>struct make_index_countup;
template<std::size_t C>using make_index_countup_t = 
	typename make_index_countup<C>::type;

####What is make_countup_sequenceのstd::size_t版。ただしmake_countup_sequenceのエイリアスではない。

###sequence_foreach ####宣言

template<class Sequence, template<class>class Functor>struct sequence_foreach;

####What is integral_sequenceの各要素をFunctorに作用させたものをintegral_sequenceに代入したものから派生したクラス。 ####template引数の要件 Sequenceはintegral_sequence Functorはtemplate引数にstd::integral_constantを受け取ってvalueをstaticメンバ定数にもつtemplateクラス ####例

template<class>struct add1;
template<std::size_t I>struct add1<std::integral_constant<std::size_t, I>>:
	std::integral_constant<std::size_t, I+1>{};

using type = plasma::integral_sequence::sequence_foreach<
	plasma::index_sequence<0, 1, 2>,add1>;

##plasma::integral_sequence::helper ###make_class_functor ####宣言

template<class Ty, template<Ty>class Functor>struct make_class_functor;
template<template<std::size_t>class Functor>using make_index_class_functor =
	make_class_functor<std::size_t, Functor>;

####What is 引数を受け取るtemplateクラスからstd::integral_constantを受け取るエイリアスを生成する。
実際にはstd::integral_constantでなくてもstaticメンバ定数valueを持てば良い。 ####メンバ

template<class T>using functor = Functor<T::value>;

####例

template<std::size_t I>struct add1:std::integral_constant<std::size_t, I+1>{};
using type = plasma::integral_sequence::helper::make_index_class_functor<add1>::functor<
	std::integral_constant<std::size_t, 1>>;
using type2 = plasma::integral_sequence::sequence_foreach<
	plasma::integral_sequence::index_sequence<0, 1, 2>,
	plasma::integral_sequence::helper::make_index_class_functor<add1>::functor>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment