Created
January 31, 2012 22:54
-
-
Save mvasilkov/1713603 to your computer and use it in GitHub Desktop.
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
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