/*
 * utility.hpp
 *
 * This file is part of Algorithms library toolkit.
 * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz)

 * Algorithms library toolkit is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * Algorithms library toolkit is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with Algorithms library toolkit.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Created on: Apr 7, 2016
 * Author: Jan Travnicek
 */

#ifndef __UTILITY_HPP_
#define __UTILITY_HPP_

#include <utility>

#include "type_traits.hpp"

#include <extensions/container/ptr_value.hpp>

namespace ext {

/**
 * \brief
 * Allow moving of copied instance of the source.
 *
 * \tparam T the type of processed instance
 *
 * \param param the source instance
 *
 * \return copy to be moved from
 */
template < class T >
inline auto move_copy ( const T & param ) {
	if constexpr ( ext::has_clone < T >::value && ! std::is_final_v < T > ) {
		return ptr_value < T > ( param );
	} else {
		return T ( param );
	}
}

namespace detail {

template < class F, std::size_t ... Is >
void constexpr_switch ( const std::size_t i, F && f, std::index_sequence < Is ... > ) {
	[ ] ( ... ) { } (
		( i == Is && ( ( void ) std::forward < F > ( f ) . operator ( ) ( std::integral_constant < size_t, Is > ( ) ), false ) ) ...
	);
}

} // namespace detail

template < std::size_t N, class F >
void constexpr_switch ( const std::size_t i, F && f ) {
	detail::constexpr_switch ( i, std::forward < F > ( f ), std::make_index_sequence < N > { } );
}

} /* namespace ext */

#endif /* __UTILITY_HPP_ */
