/usr/local/lib64/python3.6/site-packages/torch/include/c10/util
Edit: /usr/local/lib64/python3.6/site-packages/torch/include/c10/util/Metaprogramming.h (15288B)
#pragma once
#include
#include
#include
#include
#include
namespace c10 {
namespace guts {
/**
* Access information about result type or arguments from a function type.
* Example:
* using A = function_traits::return_type // A == int
* using A = function_traits::parameter_types::tuple_type
* // A == tuple
*/
template
struct function_traits {
static_assert(
!std::is_same::value,
"In function_traits, Func must be a plain function type.");
};
template
struct function_traits {
using func_type = Result(Args...);
using return_type = Result;
using parameter_types = typelist::typelist;
static constexpr auto number_of_parameters = sizeof...(Args);
};
/**
* infer_function_traits: creates a `function_traits` type for a simple
* function (pointer) or functor (lambda/struct). Currently does not support
* class methods.
*/
template
struct infer_function_traits {
using type = function_traits<
c10::guts::detail::strip_class_t>;
};
template
struct infer_function_traits {
using type = function_traits;
};
template
struct infer_function_traits {
using type = function_traits;
};
template
using infer_function_traits_t = typename infer_function_traits::type;
/**
* make_function_traits: creates a `function_traits` type given a Return type
* and a typelist of Argument types
*
* Example:
* bool f(int, int);
*
* infer_function_traits_t == make_function_traits_t>
*/
template
struct make_function_traits {
static_assert(
false_t::value,
"In guts::make_function_traits, the ArgList argument must be typelist<...>.");
};
template
struct make_function_traits> {
using type = function_traits;
};
template
using make_function_traits_t =
typename make_function_traits::type;
/**
* Use extract_arg_by_filtered_index to return the i-th argument whose
* type fulfills a given type trait. The argument itself is perfectly forwarded.
*
* Example:
* std::string arg1 = "Hello";
* std::string arg2 = "World";
* std::string&& result = extract_arg_by_filtered_index(0,
* arg1, 2.0, std::move(arg2));
*
* Warning: Taking the result by rvalue reference can cause segfaults because
* ownership will not be passed on from the original reference. The original
* reference dies after the expression and the resulting
*/
namespace detail {
template <
template
class Condition,
size_t index,
class Enable,
class... Args>
struct extract_arg_by_filtered_index_;
template <
template
class Condition,
size_t index,
class Head,
class... Tail>
struct extract_arg_by_filtered_index_<
Condition,
index,
std::enable_if_t::value>,
Head,
Tail...> {
static decltype(auto) call(Head&& /*head*/, Tail&&... tail) {
return extract_arg_by_filtered_index_::
call(std::forward(tail)...);
}
};
template <
template
class Condition,
size_t index,
class Head,
class... Tail>
struct extract_arg_by_filtered_index_<
Condition,
index,
std::enable_if_t::value && index != 0>,
Head,
Tail...> {
static decltype(auto) call(Head&& /*head*/, Tail&&... tail) {
return extract_arg_by_filtered_index_::
call(std::forward(tail)...);
}
};
template class Condition, size_t index>
struct extract_arg_by_filtered_index_ {
static void call() {
static_assert(
index != index, "extract_arg_by_filtered_index out of range.");
}
};
template <
template
class Condition,
size_t index,
class Head,
class... Tail>
struct extract_arg_by_filtered_index_<
Condition,
index,
std::enable_if_t::value && index == 0>,
Head,
Tail...> {
static decltype(auto) call(Head&& head, Tail&&... /*tail*/) {
return std::forward(head);
}
};
} // namespace detail
template class Condition, size_t index, class... Args>
decltype(auto) extract_arg_by_filtered_index(Args&&... args) {
static_assert(
is_type_condition::value,
"In extract_arg_by_filtered_index, the Condition argument must be a condition type trait, i.e. have a static constexpr bool ::value member.");
return detail::
extract_arg_by_filtered_index_::call(
std::forward(args)...);
}
/**
* Use filter_map to map a subset of the arguments to values.
* The subset is defined by type traits, and will be evaluated at compile time.
* At runtime, it will just loop over the pre-filtered arguments to create an
* std::array.
*
* Example:
* std::array result = filter_map([] (auto
* a) {return (double)a;}, 3, "bla", 4);
* // result == {3.0, 4.0}
*/
namespace detail {
template
struct filter_map_ {
template <
template
class Condition,
class Mapper,
class... Args,
size_t... INDEX>
static guts::array call(
const Mapper& mapper,
std::index_sequence,
Args&&... args) {
return guts::array{
mapper(extract_arg_by_filtered_index(
std::forward(args)...))...};
}
};
template
struct filter_map_ {
template <
template
class Condition,
class Mapper,
class... Args,
size_t... INDEX>
static guts::array call(
const Mapper& /*mapper*/,
std::index_sequence,
Args&&... /*args*/) {
return guts::array{};
}
};
} // namespace detail
template <
class ResultType,
template
class Condition,
class Mapper,
class... Args>
decltype(auto) filter_map(const Mapper& mapper, Args&&... args) {
static_assert(
is_type_condition::value,
"In filter_map, the Condition argument must be a condition type trait, i.e. have a static constexpr bool ::value member.");
static constexpr size_t num_results =
typelist::count_if>::value;
return detail::filter_map_::
template call(
mapper,
std::make_index_sequence(),
std::forward(args)...);
}
/**
* make_offset_index_sequence
* Like make_index_sequence, but starting from Start instead of 0.
*
* Example:
* make_offset_index_sequence<10, 3> == std::index_sequence<10, 11, 12>
*/
template
struct make_offset_index_sequence_impl
: make_offset_index_sequence_impl {
static_assert(
static_cast(Start) >= 0,
"make_offset_index_sequence: Start < 0");
static_assert(static_cast(N) >= 0, "make_offset_index_sequence: N < 0");
};
template
struct make_offset_index_sequence_impl {
typedef std::index_sequence type;
};
template
using make_offset_index_sequence =
typename make_offset_index_sequence_impl::type;
/**
* Use tuple_elements to extract a position-indexed subset of elements
* from the argument tuple into a result tuple.
*
* Example:
* std::tuple t = std::make_tuple(0, "HEY", 2.0);
* std::tuple result = tuple_elements(t, std::index_sequence<0,
* 2>());
*/
template
constexpr auto tuple_elements(Tuple t, std::index_sequence) {
return std::tuple...>(std::get(t)...);
}
/**
* Use tuple_take to extract the first or last n elements from the argument
* tuple into a result tuple.
*
* Example:
* std::tuple t = std::make_tuple(0, "HEY", 2.0);
* std::tuple first_two = tuple_take(t);
* std::tuple last_two = tuple_take(t);
*/
template
struct TupleTake {};
template
struct TupleTake= 0, void>> {
static auto call(Tuple t) {
constexpr size_t size = std::tuple_size();
static_assert(N <= size, "tuple_take: N > size");
return tuple_elements(t, std::make_index_sequence{});
}
};
template
struct TupleTake < Tuple,
N, std::enable_if_t> {
static auto call(Tuple t) {
constexpr size_t size = std::tuple_size();
static_assert(-N <= size, "tuple_take: -N > size");
return tuple_elements(t, make_offset_index_sequence{});
}
};
template
auto tuple_take(Tuple t) {
return TupleTake::call(t);
}
/**
* Use tuple_slice to extract a contiguous subtuple from the argument.
*
* Example:
* std::tuple t = std::make_tuple(0,
* "HEY", 2.0, false); std::tuple middle_two =
* tuple_slice(t);
*/
template
constexpr auto tuple_slice(Tuple t) {
constexpr size_t size = std::tuple_size();
static_assert(Start + N <= size, "tuple_slice: Start + N > size");
return tuple_elements(t, make_offset_index_sequence{});
}
/**
* Use tuple_map to run a mapping function over a tuple to get a new tuple.
*
* Example 1:
* auto result = tuple_map(std::tuple(3, 4, 5), []
* (int32_t a) -> int16_t {return a+1;});
* // result == std::tuple(4, 5, 6)
*
* Example 2:
* struct Mapper {
* std::string operator()(int32_t a) const {
* return std::to_string(a);
* }
* int64_t operator()(const std::string& a) const {
* return atoi(a.c_str());
* }
* };
* auto result = tuple_map(std::tuple(3, "4"),
* Mapper());
* // result == std::tuple("3", 4)
*
* Example 3:
* struct A final {
* int32_t func() {
* return 5;
* }
* };
* struct B final {
* std::string func() {
* return "5";
* }
* };
* auto result = tuple_map(std::make_tuple(A(), B()), [] (auto a) { return
* a.func(); });
* // result == std::tuple(5, "5");
*/
namespace detail {
template
auto tuple_map(
std::tuple&& tuple,
const Mapper& mapper,
std::index_sequence) {
return std::tuple(std::get(
tuple))))...>(mapper(std::forward(std::get(tuple)))...);
}
} // namespace detail
template
auto tuple_map(std::tuple&& tuple, const Mapper& mapper) {
return detail::tuple_map(
std::move(tuple), mapper, std::index_sequence_for());
}
/**
* tuple_concat concatenates several tuples into one.
*/
namespace detail {
// extract_tuple_element_by_index is a helper that takes a list of tuples and
// extracts the i-th element in a flattened view of the tuples. Example:
// extract_tuple_element_by_index<3>(tuple(2,3), tuple(4,5), tuple(6,7)) == 5.
template <
size_t index,
class HeadTuple,
class... TailTuples,
std::enable_if_t<
index::value, int> = 0> decltype(auto)
extract_tuple_element_by_index(
HeadTuple&& head_tuple,
TailTuples&&... tail_tuples) {
// TODO if constexpr instead of enable_if
return std::get(std::forward(head_tuple));
}
template <
size_t index,
class HeadTuple,
class... TailTuples,
std::enable_if_t= std::tuple_size::value, int> = 0>
decltype(auto) extract_tuple_element_by_index(
HeadTuple&& head_tuple,
TailTuples&&... tail_tuples) {
// TODO if constexpr instead of enable_if
return extract_tuple_element_by_index<
index - std::tuple_size::value,
TailTuples...>(std::forward(tail_tuples)...);
}
static_assert(
std::is_same<
int&&,
decltype(extract_tuple_element_by_index<2>(
std::tuple(2),
std::tuple(std::declval(), 3)))>::
value,
"extract_tuple_element_by_index should return rvalue references if the tuple contains them. It should not move them into a value");
template
auto tuple_concat(Tuples&&... tuples, std::index_sequence) {
return ConcatenatedTuple(extract_tuple_element_by_index(
std::forward(tuples)...)...);
}
} // namespace detail
template
auto tuple_concat(Tuples&&... tuples) {
using flattened_types =
guts::typelist::concat_t...>;
using concatenated_tuple = guts::typelist::to_tuple_t;
constexpr size_t num_elements = guts::typelist::size::value;
return detail::tuple_concat(
std::forward(tuples)...,
std::make_index_sequence());
}
/**
* Concatenate multiple integer sequences
* Example:
* concat_iseq_t, std::index_sequence<4, 2>,
* std::index_sequence<5>>
* == std::index_sequence<2, 5, 3, 4, 2, 5>
*/
template
struct concat_iseq {
static_assert(
false_t::value,
"In concat_iseq, the T arguments each must be std::integer_sequence<...> with the same IntType.");
};
template <>
struct concat_iseq<> {
using type = std::index_sequence<>;
};
template
struct concat_iseq> {
using type = std::integer_sequence;
};
template <
class IntType,
IntType... Head1Indices,
IntType... Head2Indices,
class... TailISeqs>
struct concat_iseq<
std::integer_sequence,
std::integer_sequence,
TailISeqs...> {
using type = typename concat_iseq<
std::integer_sequence,
TailISeqs...>::type;
};
template
using concat_iseq_t = typename concat_iseq::type;
} // namespace guts
} // namespace c10