/usr/include/oneapi/tbb/detail
Edit: /usr/include/oneapi/tbb/detail/_template_helpers.h (13517B)
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __TBB_detail__template_helpers_H
#define __TBB_detail__template_helpers_H
#include "_utils.h"
#include "_config.h"
#include
#include
#include
#include
#include
#include
namespace tbb {
namespace detail {
inline namespace d0 {
// An internal implementation of void_t, which can be used in SFINAE contexts
template
struct void_impl {
using type = void;
}; // struct void_impl
template
using void_t = typename void_impl::type;
// Generic SFINAE helper for expression checks, based on the idea demonstrated in ISO C++ paper n4502
template class... Checks>
struct supports_impl {
using type = std::false_type;
};
template class... Checks>
struct supports_impl...>, Checks...> {
using type = std::true_type;
};
template class... Checks>
using supports = typename supports_impl::type;
//! A template to select either 32-bit or 64-bit constant as compile time, depending on machine word size.
template
struct select_size_t_constant {
// Explicit cast is needed to avoid compiler warnings about possible truncation.
// The value of the right size, which is selected by ?:, is anyway not truncated or promoted.
static const std::size_t value = (std::size_t)((sizeof(std::size_t)==sizeof(u)) ? u : ull);
};
// TODO: do we really need it?
//! Cast between unrelated pointer types.
/** This method should be used sparingly as a last resort for dealing with
situations that inherently break strict ISO C++ aliasing rules. */
// T is a pointer type because it will be explicitly provided by the programmer as a template argument;
// U is a referent type to enable the compiler to check that "ptr" is a pointer, deducing U in the process.
template
inline T punned_cast( U* ptr ) {
std::uintptr_t x = reinterpret_cast(ptr);
return reinterpret_cast(x);
}
template
struct padded_base : T {
char pad[S - R];
};
template struct padded_base : T {};
//! Pads type T to fill out to a multiple of cache line size.
template
struct padded : padded_base {};
#if __TBB_CPP14_INTEGER_SEQUENCE_PRESENT
using std::index_sequence;
using std::make_index_sequence;
#else
template class index_sequence {};
template
struct make_index_sequence_impl : make_index_sequence_impl < N - 1, N - 1, S... > {};
template
struct make_index_sequence_impl <0, S...> {
using type = index_sequence;
};
template
using make_index_sequence = typename make_index_sequence_impl::type;
#endif /* __TBB_CPP14_INTEGER_SEQUENCE_PRESENT */
#if __TBB_CPP17_LOGICAL_OPERATIONS_PRESENT
using std::conjunction;
using std::disjunction;
#else // __TBB_CPP17_LOGICAL_OPERATIONS_PRESENT
template
struct conjunction : std::true_type {};
template
struct conjunction
: std::conditional, First>::type {};
template
struct conjunction : T {};
template
struct disjunction : std::false_type {};
template
struct disjunction
: std::conditional>::type {};
template
struct disjunction : T {};
#endif // __TBB_CPP17_LOGICAL_OPERATIONS_PRESENT
template
using iterator_value_t = typename std::iterator_traits::value_type;
template
using iterator_key_t = typename std::remove_const::first_type>::type;
template
using iterator_mapped_t = typename iterator_value_t::second_type;
template
using iterator_alloc_pair_t = std::pair>::type,
iterator_mapped_t>;
template using alloc_value_type = typename A::value_type;
template using alloc_ptr_t = typename std::allocator_traits::pointer;
template using has_allocate = decltype(std::declval&>() = std::declval().allocate(0));
template using has_deallocate = decltype(std::declval().deallocate(std::declval>(), 0));
// alloc_value_type should be checked first, because it can be used in other checks
template
using is_allocator = supports;
#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
template
inline constexpr bool is_allocator_v = is_allocator::value;
#endif
// Template class in which the "type" determines the type of the element number N in pack Args
template
struct pack_element {
using type = void;
};
template
struct pack_element {
using type = typename pack_element::type;
};
template
struct pack_element<0, T, Args...> {
using type = T;
};
template
using pack_element_t = typename pack_element::type;
template
class raii_guard {
public:
static_assert(
std::is_nothrow_copy_constructible::value &&
std::is_nothrow_move_constructible::value,
"Throwing an exception during the Func copy or move construction cause an unexpected behavior."
);
raii_guard( Func f ) noexcept : my_func(f), is_active(true) {}
raii_guard( raii_guard&& g ) noexcept : my_func(std::move(g.my_func)), is_active(g.is_active) {
g.is_active = false;
}
~raii_guard() {
if (is_active) {
my_func();
}
}
void dismiss() {
is_active = false;
}
private:
Func my_func;
bool is_active;
}; // class raii_guard
template
raii_guard make_raii_guard( Func f ) {
return raii_guard(f);
}
template
struct try_call_proxy {
try_call_proxy( Body b ) : body(b) {}
template
void on_exception( OnExceptionBody on_exception_body ) {
auto guard = make_raii_guard(on_exception_body);
body();
guard.dismiss();
}
template
void on_completion(OnCompletionBody on_completion_body) {
auto guard = make_raii_guard(on_completion_body);
body();
}
Body body;
}; // struct try_call_proxy
// Template helper function for API
// try_call(lambda1).on_exception(lambda2)
// Executes lambda1 and if it throws an exception - executes lambda2
template
try_call_proxy try_call( Body b ) {
return try_call_proxy(b);
}
#if __TBB_CPP17_IS_SWAPPABLE_PRESENT
using std::is_nothrow_swappable;
using std::is_swappable;
#else // __TBB_CPP17_IS_SWAPPABLE_PRESENT
namespace is_swappable_detail {
using std::swap;
template
using has_swap = decltype(swap(std::declval(), std::declval()));
#if _MSC_VER && _MSC_VER <= 1900 && !__INTEL_COMPILER
// Workaround for VS2015: it fails to instantiate noexcept(...) inside std::integral_constant.
template
struct noexcept_wrapper {
static const bool value = noexcept(swap(std::declval(), std::declval()));
};
template
struct is_nothrow_swappable_impl : std::integral_constant::value> {};
#else
template
struct is_nothrow_swappable_impl : std::integral_constant(), std::declval()))> {};
#endif
}
template
struct is_swappable : supports {};
template
struct is_nothrow_swappable
: conjunction, is_swappable_detail::is_nothrow_swappable_impl> {};
#endif // __TBB_CPP17_IS_SWAPPABLE_PRESENT
//! Allows to store a function parameter pack as a variable and later pass it to another function
template< typename... Types >
struct stored_pack;
template<>
struct stored_pack<>
{
using pack_type = stored_pack<>;
stored_pack() {}
// Friend front-end functions
template< typename F, typename Pack > friend void call(F&& f, Pack&& p);
template< typename Ret, typename F, typename Pack > friend Ret call_and_return(F&& f, Pack&& p);
protected:
// Ideally, ref-qualified non-static methods would be used,
// but that would greatly reduce the set of compilers where it works.
template< typename Ret, typename F, typename... Preceding >
static Ret call(F&& f, const pack_type& /*pack*/, Preceding&&... params) {
return std::forward(f)(std::forward(params)...);
}
template< typename Ret, typename F, typename... Preceding >
static Ret call(F&& f, pack_type&& /*pack*/, Preceding&&... params) {
return std::forward(f)(std::forward(params)...);
}
};
template< typename T, typename... Types >
struct stored_pack : stored_pack
{
using pack_type = stored_pack;
using pack_remainder = stored_pack;
// Since lifetime of original values is out of control, copies should be made.
// Thus references should be stripped away from the deduced type.
typename std::decay::type leftmost_value;
// Here rvalue references act in the same way as forwarding references,
// as long as class template parameters were deduced via forwarding references.
stored_pack(T&& t, Types&&... types)
: pack_remainder(std::forward(types)...), leftmost_value(std::forward(t)) {}
// Friend front-end functions
template< typename F, typename Pack > friend void call(F&& f, Pack&& p);
template< typename Ret, typename F, typename Pack > friend Ret call_and_return(F&& f, Pack&& p);
protected:
template< typename Ret, typename F, typename... Preceding >
static Ret call(F&& f, pack_type& pack, Preceding&&... params) {
return pack_remainder::template call(
std::forward(f), static_cast(pack),
std::forward(params)... , pack.leftmost_value
);
}
template< typename Ret, typename F, typename... Preceding >
static Ret call(F&& f, pack_type&& pack, Preceding&&... params) {
return pack_remainder::template call(
std::forward(f), static_cast(pack),
std::forward(params)... , std::move(pack.leftmost_value)
);
}
};
//! Calls the given function with arguments taken from a stored_pack
template< typename F, typename Pack >
void call(F&& f, Pack&& p) {
std::decay::type::template call(std::forward(f), std::forward(p));
}
template< typename Ret, typename F, typename Pack >
Ret call_and_return(F&& f, Pack&& p) {
return std::decay::type::template call(std::forward(f), std::forward(p));
}
template< typename... Types >
stored_pack save_pack(Types&&... types) {
return stored_pack(std::forward(types)...);
}
// A structure with the value which is equal to Trait::value
// but can be used in the immediate context due to parameter T
template
struct dependent_bool : std::integral_constant {};
template
struct body_arg_detector;
template
struct body_arg_detector {
using arg_type = Arg;
};
template
struct body_arg_detector {
using arg_type = Arg;
};
template
struct argument_detector;
template
struct argument_detector {
using type = typename body_arg_detector::arg_type;
};
template
struct argument_detector {
using type = Arg;
};
// Detects the argument type of callable, works for callable with one argument.
template
using argument_type_of = typename argument_detector::type>::type;
template
struct type_identity {
using type = T;
};
template
using type_identity_t = typename type_identity::type;
} // inline namespace d0
} // namespace detail
} // namespace tbb
#endif // __TBB_detail__template_helpers_H