Skip to content

Instantly share code, notes, and snippets.

@mvasilkov
Created January 31, 2012 22:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mvasilkov/1713603 to your computer and use it in GitHub Desktop.
Save mvasilkov/1713603 to your computer and use it in GitHub Desktop.
template< class, class >
class Permutation;
template< class OUT_TYPE, class... IN_TYPES, uint32_t... INDEXES >
class Permutation<
std::function< OUT_TYPE (IN_TYPES...) >, // тип целевой функции
UintContainer< INDEXES... > > // перестановка аргументов
{
public:
typedef std::function< OUT_TYPE (IN_TYPES...) > FuncType;
typedef std::function< OUT_TYPE (typename GetNthType< INDEXES, TypeContainer<IN_TYPES...> >::Result...) > NewFuncType;
Permutation( Permutation const& perm ): _function( perm._function ) { };
Permutation( FuncType const& f ): _function( f ) { };
private:
// вспомогательный метод для развертывания найденной обратной перестановки
template< uint32_t... INVERSE >
inline OUT_TYPE apply( UintContainer< INVERSE... >, // нам нужен только тип, т.е. индексы
typename GetNthType< INDEXES, TypeContainer<IN_TYPES...> >::Result... values )
{
// сохраняем аргументы в std::tuple по индексу перестановки
std::tuple< typename GetNthType< INDEXES, TypeContainer<IN_TYPES...> >::Result... > data( values... );
// извлекаем аргументы из std::tuple по инверсному индексу
return _function( std::get< INVERSE > (data)... );
};
public:
inline OUT_TYPE operator()( typename GetNthType< INDEXES, TypeContainer<IN_TYPES...> >::Result... values )
{
// находим инверсную перестановку
typename InversePermutation< UintContainer<INDEXES...> >::Result inverse;
return apply( inverse, values... );
};
private:
Permutation();
FuncType _function;
};
// функция для удобства; заворачивает Permutation в std::function
template< uint32_t... INDEXES, class FUNC_TYPE >
auto permute( FUNC_TYPE const& f ) ->
typename Permutation<FUNC_TYPE,
// дополняем перестановку, т.е. добавляем в конец недостающие индексы
typename ComplementRange<
GetArgumentsCount<FUNC_TYPE>::Result, UintContainer < INDEXES... >
>::Result
>::NewFuncType
{
typedef Permutation<FUNC_TYPE,
typename ComplementRange<
GetArgumentsCount<FUNC_TYPE>::Result, UintContainer < INDEXES... >
>::Result
> PermutationType;
return PermutationType(f);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment