@@ -0,0 +1,185 @@ | |||||
#pragma once | |||||
/* C++ standards */ | |||||
#if __cplusplus >= 201103L | |||||
#define cppmp_supports_cpp11 1 | |||||
#endif | |||||
#if __cplusplus >= 201402L | |||||
#define cppmp_supports_cpp14 1 | |||||
#endif | |||||
#if __cplusplus >= 201703L | |||||
#define cppmp_supports_cpp17 1 | |||||
#endif | |||||
/* C++ features */ | |||||
#if __cpp_variable_templates >= 201304L | |||||
#define cppmp_supports_variable_templates 1 | |||||
#endif | |||||
#if __cpp_constexpr >= 201603L | |||||
#define cppmp_supports_constexpr_lambda 1 | |||||
#endif | |||||
/* GCC */ | |||||
#ifdef __GNUC__ | |||||
#define cppmp_gcc_version (__GNUC__ * 10000 \ | |||||
+ __GNUC_MINOR__ * 100 \ | |||||
+ __GNUC_PATCHLEVEL__) | |||||
#endif | |||||
/* Macros */ | |||||
#ifdef cppmp_supports_constexpr_lambda | |||||
#define cppmp_constexpr_lambda constexpr | |||||
#else | |||||
#define cppmp_constexpr_lambda | |||||
#endif | |||||
/* Supported Traits */ | |||||
#ifdef cppmp_supports_cpp11 | |||||
#define cppmp_std_supports_remove_const 1 | |||||
#define cppmp_std_supports_remove_volatile 1 | |||||
#define cppmp_std_supports_remove_cv 1 | |||||
#define cppmp_std_supports_add_const 1 | |||||
#define cppmp_std_supports_add_volatile 1 | |||||
#define cppmp_std_supports_add_cv 1 | |||||
#define cppmp_std_supports_remove_reference 1 | |||||
#define cppmp_std_supports_add_lvalue_reference 1 | |||||
#define cppmp_std_supports_add_rvalue_reference 1 | |||||
#define cppmp_std_supports_make_signed 1 | |||||
#define cppmp_std_supports_make_unsigned 1 | |||||
#define cppmp_std_supports_remove_extent 1 | |||||
#define cppmp_std_supports_remove_all_extents 1 | |||||
#define cppmp_std_supports_add_pointer 1 | |||||
#define cppmp_std_supports_remove_pointer 1 | |||||
#define cppmp_std_supports_decay 1 | |||||
#define cppmp_std_supports_common_type 1 | |||||
#define cppmp_std_supports_underlying_type 1 | |||||
#define cppmp_std_supports_aligned_storage 1 | |||||
#if !defined(cppmp_gcc_version) or cppmp_gcc_version >= 50000 | |||||
#define cppmp_std_supports_aligned_union 1 | |||||
#endif | |||||
#ifndef cppmp_supports_cpp20 | |||||
#define cppmp_std_supports_result_of 1 | |||||
#endif | |||||
#define cppmp_std_supports_enable_if 1 | |||||
#define cppmp_std_supports_conditional 1 | |||||
#define cppmp_std_supports_is_void 1 | |||||
#define cppmp_std_supports_is_integral 1 | |||||
#define cppmp_std_supports_is_floating_point 1 | |||||
#define cppmp_std_supports_is_array 1 | |||||
#define cppmp_std_supports_is_pointer 1 | |||||
#define cppmp_std_supports_is_lvalue_reference 1 | |||||
#define cppmp_std_supports_is_rvalue_reference 1 | |||||
#define cppmp_std_supports_is_member_object_pointer 1 | |||||
#define cppmp_std_supports_is_member_function_pointer 1 | |||||
#define cppmp_std_supports_is_enum 1 | |||||
#define cppmp_std_supports_is_union 1 | |||||
#define cppmp_std_supports_is_class 1 | |||||
#define cppmp_std_supports_is_function 1 | |||||
#define cppmp_std_supports_is_reference 1 | |||||
#define cppmp_std_supports_is_arithmetic 1 | |||||
#define cppmp_std_supports_is_fundamental 1 | |||||
#define cppmp_std_supports_is_object 1 | |||||
#define cppmp_std_supports_is_scalar 1 | |||||
#define cppmp_std_supports_is_compound 1 | |||||
#define cppmp_std_supports_is_member_pointer 1 | |||||
#define cppmp_std_supports_is_const 1 | |||||
#define cppmp_std_supports_is_volatile 1 | |||||
#define cppmp_std_supports_is_trivial 1 | |||||
#define cppmp_std_supports_is_standard_layout 1 | |||||
#define cppmp_std_supports_is_pod 1 | |||||
#define cppmp_std_supports_is_empty 1 | |||||
#define cppmp_std_supports_is_polymorphic 1 | |||||
#define cppmp_std_supports_is_abstract 1 | |||||
#define cppmp_std_supports_is_signed 1 | |||||
#define cppmp_std_supports_is_unsigned 1 | |||||
#define cppmp_std_supports_is_constructible 1 | |||||
#define cppmp_std_supports_is_default_constructible 1 | |||||
#define cppmp_std_supports_is_copy_constructible 1 | |||||
#define cppmp_std_supports_is_move_constructible 1 | |||||
#define cppmp_std_supports_is_assignable 1 | |||||
#define cppmp_std_supports_is_copy_assignable 1 | |||||
#define cppmp_std_supports_is_move_assignable 1 | |||||
#define cppmp_std_supports_is_destructible 1 | |||||
#if !defined(cppmp_gcc_version) or cppmp_gcc_version >= 50000 | |||||
#define cppmp_std_supports_is_trivially_constructible 1 | |||||
#define cppmp_std_supports_is_trivially_default_constructible 1 | |||||
#define cppmp_std_supports_is_trivially_copy_constructible 1 | |||||
#define cppmp_std_supports_is_trivially_move_constructible 1 | |||||
#define cppmp_std_supports_is_trivially_assignable 1 | |||||
#define cppmp_std_supports_is_trivially_copy_assignable 1 | |||||
#define cppmp_std_supports_is_trivially_move_assignable 1 | |||||
#define cppmp_std_supports_is_trivially_destructible 1 | |||||
#define cppmp_std_supports_is_trivially_copyable 1 | |||||
#endif | |||||
#define cppmp_std_supports_is_nothrow_constructible 1 | |||||
#define cppmp_std_supports_is_nothrow_default_constructible 1 | |||||
#define cppmp_std_supports_is_nothrow_copy_constructible 1 | |||||
#define cppmp_std_supports_is_nothrow_move_constructible 1 | |||||
#define cppmp_std_supports_is_nothrow_assignable 1 | |||||
#define cppmp_std_supports_is_nothrow_copy_assignable 1 | |||||
#define cppmp_std_supports_is_nothrow_move_assignable 1 | |||||
#define cppmp_std_supports_is_nothrow_destructible 1 | |||||
#define cppmp_std_supports_has_virtual_destructor 1 | |||||
#define cppmp_std_supports_alignment_of 1 | |||||
#define cppmp_std_supports_rank 1 | |||||
#define cppmp_std_supports_extent 1 | |||||
#define cppmp_std_supports_is_same 1 | |||||
#define cppmp_std_supports_is_base_of 1 | |||||
#define cppmp_std_supports_is_convertible 1 | |||||
#endif | |||||
#ifdef cppmp_supports_cpp14 | |||||
#define cppmp_std_supports_is_null_pointer 1 | |||||
#define cppmp_std_supports_is_final 1 | |||||
#endif | |||||
#ifdef cppmp_supports_cpp17 | |||||
#define cppmp_std_supports_invoke_result 1 | |||||
#define cppmp_std_supports_conjunction 1 | |||||
#define cppmp_std_supports_disjunction 1 | |||||
#define cppmp_std_supports_negation 1 | |||||
#define cppmp_std_supports_is_aggregate 1 | |||||
#define cppmp_std_supports_is_swappable_with 1 | |||||
#define cppmp_std_supports_is_swappable 1 | |||||
#define cppmp_std_supports_is_nothrow_swappable_with 1 | |||||
#define cppmp_std_supports_is_nothrow_swappable 1 | |||||
#define cppmp_std_supports_has_unique_object_representations 1 | |||||
#define cppmp_std_supports_is_invocable 1 | |||||
#define cppmp_std_supports_is_invocable_r 1 | |||||
#define cppmp_std_supports_is_nothrow_invocable 1 | |||||
#define cppmp_std_supports_is_nothrow_invocable_r 1 | |||||
#endif | |||||
#ifdef cppmp_supports_cpp20 | |||||
#define cppmp_std_supports_remove_cvref 1 | |||||
#define cppmp_std_supports_is_bounded_array 1 | |||||
#define cppmp_std_supports_is_unbounded_array 1 | |||||
#define cppmp_std_supports_has_strong_structural_equality 1 | |||||
#define cppmp_std_supports_is_nothrow_convertible 1 | |||||
#define cppmp_std_supports_is_layout_compatible 1 | |||||
#define cppmp_std_supports_is_pointer_interconvertible_base_of 1 | |||||
#endif |
@@ -1,30 +1,45 @@ | |||||
#pragma once | #pragma once | ||||
#include "types.h" | |||||
#include "../config.h" | |||||
#define cppmp_define_checker(name) \ | #define cppmp_define_checker(name) \ | ||||
template<typename... T> \ | template<typename... T> \ | ||||
struct name \ | struct name \ | ||||
: public integral_constant<decltype(std::name<T...>::value), std::name<T...>::value> \ | : public integral_constant<decltype(std::name<T...>::value), std::name<T...>::value> \ | ||||
{ }; \ | { }; \ | ||||
\ | \ | ||||
template<typename... T> \ | |||||
constexpr decltype(auto) name ## _v = name<T...>::value; | |||||
cppmp_define_checker_var(name) | |||||
#include "types.h" | |||||
#ifdef cppmp_supports_variable_templates | |||||
#define cppmp_define_checker_var(name) \ | |||||
template<typename... T> \ | |||||
constexpr decltype(auto) name ## _v = name<T...>::value; | |||||
#else | |||||
#define cppmp_define_checker_var(name) | |||||
#endif | |||||
namespace cppmp | namespace cppmp | ||||
{ | { | ||||
namespace __impl | |||||
{ | |||||
template<typename T> | |||||
struct is_valid; | |||||
} | |||||
/** | /** | ||||
* @brief Evaluates to true_t if the passed template parameters are valid, false_t otherwise. | * @brief Evaluates to true_t if the passed template parameters are valid, false_t otherwise. | ||||
*/ | */ | ||||
template<typename T, typename = void> | |||||
struct is_valid; | |||||
template<typename T> | |||||
struct is_valid | |||||
: public __impl::is_valid<T> | |||||
{ }; | |||||
/** | |||||
* @brief Is true if the passed template parameters are valid, false otherwise. | |||||
*/ | |||||
template<typename... T> | |||||
constexpr decltype(auto) is_valid_v = is_valid<T...>::value; | |||||
cppmp_define_checker_var(is_valid) | |||||
/** | /** | ||||
* @brief Evaluates to true_t if T is a specialization if T_template, false_t otherwise. | * @brief Evaluates to true_t if T is a specialization if T_template, false_t otherwise. | ||||
@@ -32,11 +47,10 @@ namespace cppmp | |||||
template<typename T, template <typename...> class T_template> | template<typename T, template <typename...> class T_template> | ||||
struct is_specialization_of; | struct is_specialization_of; | ||||
/** | |||||
* @brief Evaluates to true if T is a specialization if T_template, false otherwise. | |||||
*/ | |||||
#ifdef cppmp_supports_variable_templates | |||||
template<typename T, template <typename...> class T_template> | template<typename T, template <typename...> class T_template> | ||||
constexpr decltype(auto) is_specialization_of_v = is_specialization_of<T, T_template>::value; | constexpr decltype(auto) is_specialization_of_v = is_specialization_of<T, T_template>::value; | ||||
#endif | |||||
/** | /** | ||||
* @brief Evaluates to true_t if all passed parameters are true, false_t otherwise. | * @brief Evaluates to true_t if all passed parameters are true, false_t otherwise. | ||||
@@ -44,93 +58,345 @@ namespace cppmp | |||||
template<bool... B> | template<bool... B> | ||||
struct is_true; | struct is_true; | ||||
/** | |||||
* @brief Evaluates to true if all passed parameters are true, false otherwise. | |||||
*/ | |||||
#ifdef cppmp_supports_variable_templates | |||||
template<bool... B> | template<bool... B> | ||||
constexpr decltype(auto) is_true_v = is_true<B...>::value; | constexpr decltype(auto) is_true_v = is_true<B...>::value; | ||||
#endif | |||||
/* primary type categories */ | |||||
#ifdef cppmp_std_supports_is_void | |||||
cppmp_define_checker(is_void); | cppmp_define_checker(is_void); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_null_pointer | |||||
cppmp_define_checker(is_null_pointer); | cppmp_define_checker(is_null_pointer); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_integral | |||||
cppmp_define_checker(is_integral); | cppmp_define_checker(is_integral); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_floating_point | |||||
cppmp_define_checker(is_floating_point); | cppmp_define_checker(is_floating_point); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_array | |||||
cppmp_define_checker(is_array); | cppmp_define_checker(is_array); | ||||
cppmp_define_checker(is_enum); | |||||
cppmp_define_checker(is_union); | |||||
cppmp_define_checker(is_class); | |||||
cppmp_define_checker(is_function); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_pointer | |||||
cppmp_define_checker(is_pointer); | cppmp_define_checker(is_pointer); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_lvalue_reference | |||||
cppmp_define_checker(is_lvalue_reference); | cppmp_define_checker(is_lvalue_reference); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_rvalue_reference | |||||
cppmp_define_checker(is_rvalue_reference); | cppmp_define_checker(is_rvalue_reference); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_member_object_pointer | |||||
cppmp_define_checker(is_member_object_pointer); | cppmp_define_checker(is_member_object_pointer); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_member_function_pointer | |||||
cppmp_define_checker(is_member_function_pointer); | cppmp_define_checker(is_member_function_pointer); | ||||
cppmp_define_checker(is_fundamental); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_enum | |||||
cppmp_define_checker(is_enum); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_union | |||||
cppmp_define_checker(is_union); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_class | |||||
cppmp_define_checker(is_class); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_function | |||||
cppmp_define_checker(is_function); | |||||
#endif | |||||
/* composite type categories */ | |||||
#ifdef cppmp_std_supports_is_reference | |||||
cppmp_define_checker(is_reference); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_arithmetic | |||||
cppmp_define_checker(is_arithmetic); | cppmp_define_checker(is_arithmetic); | ||||
cppmp_define_checker(is_scalar); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_fundamental | |||||
cppmp_define_checker(is_fundamental); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_object | |||||
cppmp_define_checker(is_object); | cppmp_define_checker(is_object); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_scalar | |||||
cppmp_define_checker(is_scalar); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_compound | |||||
cppmp_define_checker(is_compound); | cppmp_define_checker(is_compound); | ||||
cppmp_define_checker(is_reference); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_member_pointer | |||||
cppmp_define_checker(is_member_pointer); | cppmp_define_checker(is_member_pointer); | ||||
#endif | |||||
/* type properties */ | |||||
#ifdef cppmp_std_supports_is_const | |||||
cppmp_define_checker(is_const); | cppmp_define_checker(is_const); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_volatile | |||||
cppmp_define_checker(is_volatile); | cppmp_define_checker(is_volatile); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_trivial | |||||
cppmp_define_checker(is_trivial); | cppmp_define_checker(is_trivial); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_trivially_copyable | |||||
cppmp_define_checker(is_trivially_copyable); | cppmp_define_checker(is_trivially_copyable); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_standard_layout | |||||
cppmp_define_checker(is_standard_layout); | cppmp_define_checker(is_standard_layout); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_pod | |||||
cppmp_define_checker(is_pod); | cppmp_define_checker(is_pod); | ||||
cppmp_define_checker(is_literal_type); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_empty | |||||
cppmp_define_checker(is_empty); | cppmp_define_checker(is_empty); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_polymorphic | |||||
cppmp_define_checker(is_polymorphic); | cppmp_define_checker(is_polymorphic); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_abstract | |||||
cppmp_define_checker(is_abstract); | cppmp_define_checker(is_abstract); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_final | |||||
cppmp_define_checker(is_final); | cppmp_define_checker(is_final); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_aggregate | |||||
cppmp_define_checker(is_aggregate); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_signed | |||||
cppmp_define_checker(is_signed); | cppmp_define_checker(is_signed); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_unsigned | |||||
cppmp_define_checker(is_unsigned); | cppmp_define_checker(is_unsigned); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_bounded_array | |||||
cppmp_define_checker(is_bounded_array); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_unbounded_array | |||||
cppmp_define_checker(is_unbounded_array); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_constructible | |||||
cppmp_define_checker(is_constructible); | cppmp_define_checker(is_constructible); | ||||
cppmp_define_checker(is_trivially_constructible); | |||||
cppmp_define_checker(is_nothrow_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_default_constructible | |||||
cppmp_define_checker(is_default_constructible); | cppmp_define_checker(is_default_constructible); | ||||
cppmp_define_checker(is_trivially_default_constructible); | |||||
cppmp_define_checker(is_nothrow_default_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_copy_constructible | |||||
cppmp_define_checker(is_copy_constructible); | cppmp_define_checker(is_copy_constructible); | ||||
cppmp_define_checker(is_trivially_copy_constructible); | |||||
cppmp_define_checker(is_nothrow_copy_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_move_constructible | |||||
cppmp_define_checker(is_move_constructible); | cppmp_define_checker(is_move_constructible); | ||||
cppmp_define_checker(is_trivially_move_constructible); | |||||
cppmp_define_checker(is_nothrow_move_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_assignable | |||||
cppmp_define_checker(is_assignable); | cppmp_define_checker(is_assignable); | ||||
cppmp_define_checker(is_trivially_assignable); | |||||
cppmp_define_checker(is_nothrow_assignable); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_copy_assignable | |||||
cppmp_define_checker(is_copy_assignable); | cppmp_define_checker(is_copy_assignable); | ||||
cppmp_define_checker(is_trivially_copy_assignable); | |||||
cppmp_define_checker(is_nothrow_copy_assignable); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_move_assignable | |||||
cppmp_define_checker(is_move_assignable); | cppmp_define_checker(is_move_assignable); | ||||
cppmp_define_checker(is_trivially_move_assignable); | |||||
cppmp_define_checker(is_nothrow_move_assignable); | |||||
cppmp_define_checker(is_destructible); | |||||
cppmp_define_checker(is_trivially_destructible); | |||||
cppmp_define_checker(is_nothrow_destructible); | |||||
cppmp_define_checker(has_virtual_destructor); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_swappable_with | |||||
cppmp_define_checker(is_swappable_with); | cppmp_define_checker(is_swappable_with); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_swappable | |||||
cppmp_define_checker(is_swappable); | cppmp_define_checker(is_swappable); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_destructible | |||||
cppmp_define_checker(is_destructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_trivially_constructible | |||||
cppmp_define_checker(is_trivially_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_trivially_default_constructible | |||||
cppmp_define_checker(is_trivially_default_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_trivially_copy_constructible | |||||
cppmp_define_checker(is_trivially_copy_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_trivially_move_constructible | |||||
cppmp_define_checker(is_trivially_move_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_trivially_assignable | |||||
cppmp_define_checker(is_trivially_assignable); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_trivially_copy_assignable | |||||
cppmp_define_checker(is_trivially_copy_assignable); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_trivially_move_assignable | |||||
cppmp_define_checker(is_trivially_move_assignable); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_trivially_destructible | |||||
cppmp_define_checker(is_trivially_destructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_constructible | |||||
cppmp_define_checker(is_nothrow_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_default_constructible | |||||
cppmp_define_checker(is_nothrow_default_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_copy_constructible | |||||
cppmp_define_checker(is_nothrow_copy_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_move_constructible | |||||
cppmp_define_checker(is_nothrow_move_constructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_assignable | |||||
cppmp_define_checker(is_nothrow_assignable); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_copy_assignable | |||||
cppmp_define_checker(is_nothrow_copy_assignable); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_move_assignable | |||||
cppmp_define_checker(is_nothrow_move_assignable); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_swappable_with | |||||
cppmp_define_checker(is_nothrow_swappable_with); | cppmp_define_checker(is_nothrow_swappable_with); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_swappable | |||||
cppmp_define_checker(is_nothrow_swappable); | cppmp_define_checker(is_nothrow_swappable); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_destructible | |||||
cppmp_define_checker(is_nothrow_destructible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_has_virtual_destructor | |||||
cppmp_define_checker(has_virtual_destructor); | |||||
#endif | |||||
#ifdef cppmp_std_supports_has_unique_object_representations | |||||
cppmp_define_checker(has_unique_object_representations); | |||||
#endif | |||||
#ifdef cppmp_std_supports_has_strong_structural_equality | |||||
cppmp_define_checker(has_strong_structural_equality); | |||||
#endif | |||||
/* type property queries */ | |||||
#ifdef cppmp_std_supports_alignment_of | |||||
cppmp_define_checker(alignment_of); | cppmp_define_checker(alignment_of); | ||||
#endif | |||||
#ifdef cppmp_std_supports_rank | |||||
cppmp_define_checker(rank); | cppmp_define_checker(rank); | ||||
#endif | |||||
#ifdef cppmp_std_supports_extent | |||||
cppmp_define_checker(extent); | cppmp_define_checker(extent); | ||||
#endif | |||||
/* type relations */ | |||||
#ifdef cppmp_std_supports_is_same | |||||
cppmp_define_checker(is_same); | cppmp_define_checker(is_same); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_base_of | |||||
cppmp_define_checker(is_base_of); | cppmp_define_checker(is_base_of); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_convertible | |||||
cppmp_define_checker(is_convertible); | cppmp_define_checker(is_convertible); | ||||
#endif | |||||
#if __cplusplus >= 201703L | |||||
cppmp_define_checker(has_unique_object_representations); | |||||
cppmp_define_checker(is_aggregate); | |||||
#ifdef cppmp_std_supports_is_nothrow_convertible | |||||
cppmp_define_checker(is_nothrow_convertible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_layout_compatible | |||||
cppmp_define_checker(is_layout_compatible); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_pointer_interconvertible_base_of | |||||
cppmp_define_checker(is_pointer_interconvertible_base_of); | |||||
#endif | |||||
#ifdef cppmp_std_supports_is_invocable | |||||
cppmp_define_checker(is_invocable); | cppmp_define_checker(is_invocable); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_invocable_r | |||||
cppmp_define_checker(is_invocable_r); | cppmp_define_checker(is_invocable_r); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_invocable | |||||
cppmp_define_checker(is_nothrow_invocable); | cppmp_define_checker(is_nothrow_invocable); | ||||
#endif | |||||
#ifdef cppmp_std_supports_is_nothrow_invocable_r | |||||
cppmp_define_checker(is_nothrow_invocable_r); | cppmp_define_checker(is_nothrow_invocable_r); | ||||
#endif | #endif | ||||
} | } | ||||
#undef cppmp_define_checker | #undef cppmp_define_checker | ||||
#undef cppmp_define_checker_var | |||||
#include "checker.inl" | #include "checker.inl" |
@@ -25,24 +25,24 @@ namespace cppmp | |||||
: public true_t | : public true_t | ||||
{ }; | { }; | ||||
} | |||||
/* is_valid */ | |||||
/* is_valid */ | |||||
template<typename T, std::size_t = sizeof(T)> | |||||
std::true_type is_valid_impl(T *); | |||||
template<typename T, typename> | |||||
struct is_valid | |||||
: public false_t | |||||
{ }; | |||||
std::false_type is_valid_impl(...); | |||||
template<typename T> | |||||
struct is_valid<T, void_t<decltype(sizeof(T))>> | |||||
: public true_t | |||||
{ }; | |||||
template<typename T> | |||||
struct is_valid | |||||
: public decltype(is_valid_impl(std::declval<T*>())) | |||||
{ }; | |||||
template<> | |||||
struct is_valid<void, void> | |||||
: public true_t | |||||
{ }; | |||||
template<> | |||||
struct is_valid<void> | |||||
: public true_t | |||||
{ }; | |||||
} | |||||
/* is_specialization_of */ | /* is_specialization_of */ | ||||
@@ -5,12 +5,6 @@ | |||||
namespace cppmp | namespace cppmp | ||||
{ | { | ||||
/** | |||||
* @brief Boolean constant value. | |||||
*/ | |||||
template<bool B> | |||||
constexpr bool_t<B> bool_c; | |||||
/** | /** | ||||
* @brief True boolean constant value. | * @brief True boolean constant value. | ||||
*/ | */ | ||||
@@ -21,15 +15,25 @@ namespace cppmp | |||||
*/ | */ | ||||
constexpr false_t false_c; | constexpr false_t false_c; | ||||
/** | |||||
* @brief Zero size constant value, | |||||
*/ | |||||
constexpr zero_t zero_c; | |||||
#ifdef cppmp_supports_variable_templates | |||||
/** | |||||
* @brief Boolean constant value. | |||||
*/ | |||||
template<bool B> | |||||
constexpr bool_t<B> bool_c; | |||||
/** | /** | ||||
* @brief Size constant value. | * @brief Size constant value. | ||||
*/ | */ | ||||
template<std::size_t I> | template<std::size_t I> | ||||
constexpr size_t<I> size_c; | constexpr size_t<I> size_c; | ||||
/** | |||||
* @brief Zero size constant value, | |||||
*/ | |||||
constexpr zero_t zero_c; | |||||
#endif | |||||
} | } |
@@ -1,5 +1,7 @@ | |||||
#pragma once | #pragma once | ||||
#include <cstddef> | |||||
#define cppmp_define_modifier(name) \ | #define cppmp_define_modifier(name) \ | ||||
template<typename... T> \ | template<typename... T> \ | ||||
struct name \ | struct name \ | ||||
@@ -18,29 +20,118 @@ namespace cppmp | |||||
template<typename T> | template<typename T> | ||||
using decay_t = typename decay<T>::type; | using decay_t = typename decay<T>::type; | ||||
cppmp_define_modifier(remove_cv); | |||||
/* const-volatile modifications */ | |||||
#ifdef cppmp_std_supports_remove_const | |||||
cppmp_define_modifier(remove_const); | cppmp_define_modifier(remove_const); | ||||
#endif | |||||
#ifdef cppmp_std_supports_remove_volatile | |||||
cppmp_define_modifier(remove_volatile); | cppmp_define_modifier(remove_volatile); | ||||
cppmp_define_modifier(add_cv); | |||||
#endif | |||||
#ifdef cppmp_std_supports_remove_cv | |||||
cppmp_define_modifier(remove_cv); | |||||
#endif | |||||
#ifdef cppmp_std_supports_add_const | |||||
cppmp_define_modifier(add_const); | cppmp_define_modifier(add_const); | ||||
#endif | |||||
#ifdef cppmp_std_supports_add_volatile | |||||
cppmp_define_modifier(add_volatile); | cppmp_define_modifier(add_volatile); | ||||
#endif | |||||
#ifdef cppmp_std_supports_add_cv | |||||
cppmp_define_modifier(add_cv); | |||||
#endif | |||||
/* reference modifications */ | |||||
#ifdef cppmp_std_supports_remove_reference | |||||
cppmp_define_modifier(remove_reference); | cppmp_define_modifier(remove_reference); | ||||
#endif | |||||
#ifdef cppmp_std_supports_add_lvalue_reference | |||||
cppmp_define_modifier(add_lvalue_reference); | cppmp_define_modifier(add_lvalue_reference); | ||||
#endif | |||||
#ifdef cppmp_std_supports_add_rvalue_reference | |||||
cppmp_define_modifier(add_rvalue_reference); | cppmp_define_modifier(add_rvalue_reference); | ||||
cppmp_define_modifier(remove_pointer); | |||||
cppmp_define_modifier(add_pointer); | |||||
#endif | |||||
/* sign modifications */ | |||||
#ifdef cppmp_std_supports_make_signed | |||||
cppmp_define_modifier(make_signed); | cppmp_define_modifier(make_signed); | ||||
#endif | |||||
#ifdef cppmp_std_supports_make_unsigned | |||||
cppmp_define_modifier(make_unsigned); | cppmp_define_modifier(make_unsigned); | ||||
#endif | |||||
/* array modifications */ | |||||
#ifdef cppmp_std_supports_remove_extent | |||||
cppmp_define_modifier(remove_extent); | cppmp_define_modifier(remove_extent); | ||||
#endif | |||||
#ifdef cppmp_std_supports_remove_all_extents | |||||
cppmp_define_modifier(remove_all_extents); | cppmp_define_modifier(remove_all_extents); | ||||
#endif | |||||
/* pointer modifications */ | |||||
#ifdef cppmp_std_supports_add_pointer | |||||
cppmp_define_modifier(add_pointer); | |||||
#endif | |||||
#ifdef cppmp_std_supports_remove_pointer | |||||
cppmp_define_modifier(remove_pointer); | |||||
#endif | |||||
/* other transformations */ | |||||
#ifdef cppmp_std_supports_remove_cvref | |||||
cppmp_define_modifier(remove_cvref); | |||||
#endif | |||||
#ifdef cppmp_std_supports_common_type | |||||
cppmp_define_modifier(common_type); | cppmp_define_modifier(common_type); | ||||
#endif | |||||
#ifdef cppmp_std_supports_underlying_type | |||||
cppmp_define_modifier(underlying_type); | cppmp_define_modifier(underlying_type); | ||||
#endif | |||||
#ifdef cppmp_std_supports_result_of | |||||
cppmp_define_modifier(result_of); | cppmp_define_modifier(result_of); | ||||
#endif | |||||
#if __cplusplus >= 201703L | |||||
#ifdef cppmp_std_supports_invoke_result | |||||
cppmp_define_modifier(invoke_result); | cppmp_define_modifier(invoke_result); | ||||
#endif | #endif | ||||
#ifdef cppmp_std_supports_aligned_storage | |||||
template <std::size_t Len, std::size_t Align> | |||||
struct aligned_storage | |||||
: public std::aligned_storage<Len, Align> | |||||
{ }; | |||||
template <std::size_t Len, std::size_t Align> | |||||
using aligned_storage_t = typename aligned_storage<Len, Align>::type; | |||||
#endif | |||||
#ifdef cppmp_std_supports_aligned_union | |||||
template <std::size_t Len, class... Types> | |||||
struct aligned_union | |||||
: public std::aligned_union<Len, Types...> | |||||
{ }; | |||||
template <std::size_t Len, class... Types> | |||||
using aligned_union_t = typename aligned_union<Len, Types...>::type; | |||||
#endif | |||||
} | } | ||||
#undef cppmp_define_modifier | #undef cppmp_define_modifier | ||||
@@ -1,5 +1,6 @@ | |||||
#pragma once | #pragma once | ||||
#include <cstddef> | |||||
#include <type_traits> | #include <type_traits> | ||||
namespace cppmp | namespace cppmp | ||||
@@ -18,8 +19,10 @@ namespace cppmp | |||||
struct type_t | struct type_t | ||||
{ }; | { }; | ||||
#ifdef cppmp_supports_variable_templates | |||||
template<typename X> | template<typename X> | ||||
constexpr decltype(auto) type_v = type_t<X> { }; | constexpr decltype(auto) type_v = type_t<X> { }; | ||||
#endif | |||||
/** | /** | ||||
* @brief Simple type list. | * @brief Simple type list. | ||||
@@ -1,5 +1,6 @@ | |||||
#pragma once | #pragma once | ||||
#include <utility> | |||||
#include <cppmp/core/types.h> | #include <cppmp/core/types.h> | ||||
#include <cppmp/core/checker.h> | #include <cppmp/core/checker.h> | ||||
@@ -8,16 +9,19 @@ namespace cppmp | |||||
namespace __impl | namespace __impl | ||||
{ | { | ||||
template<typename T> | |||||
struct is_default_impl | |||||
{ | |||||
private: | |||||
template<typename X> | |||||
static void impl(decltype(typename X::is_default(), int())); | |||||
template<typename X, typename = void> | |||||
struct is_valid_builder | |||||
: public cppmp::true_t | |||||
{ }; | |||||
template<typename X> | |||||
static bool impl(char); | |||||
template<typename X> | |||||
struct is_valid_builder<X, cppmp::void_t<typename X::is_default>> | |||||
: public cppmp::false_t | |||||
{ }; | |||||
public: | |||||
static const bool value = std::is_same<void, decltype(impl<T>(0))>::value; | |||||
}; | |||||
} | } | ||||
@@ -34,14 +38,16 @@ namespace cppmp | |||||
*/ | */ | ||||
template<typename... T_args> | template<typename... T_args> | ||||
struct is_valid | struct is_valid | ||||
: public __impl::is_valid_builder<T_builder<list<T_args...>>> | |||||
: public bool_t<!__impl::is_default_impl<T_builder<list<T_args...>>>::value> | |||||
{ }; | { }; | ||||
#ifdef cppmp_supports_variable_templates | |||||
/** | /** | ||||
* @brief Evaluates to true if the passed arguments would create a valid object, false otherwise. | * @brief Evaluates to true if the passed arguments would create a valid object, false otherwise. | ||||
*/ | */ | ||||
template<typename... T_args> | template<typename... T_args> | ||||
static constexpr bool is_valid_v = is_valid<T_args...>::value; | static constexpr bool is_valid_v = is_valid<T_args...>::value; | ||||
#endif | |||||
/** | /** | ||||
* @brief Invoke the builder to create the requested object. | * @brief Invoke the builder to create the requested object. | ||||
@@ -29,11 +29,13 @@ namespace cppmp | |||||
template<typename T> | template<typename T> | ||||
struct is_getter; | struct is_getter; | ||||
#ifdef cppmp_supports_variable_templates | |||||
/** | /** | ||||
* @brief Is true if the passed type is an getter, false otherwise. | * @brief Is true if the passed type is an getter, false otherwise. | ||||
*/ | */ | ||||
template<typename T> | template<typename T> | ||||
constexpr decltype(auto) is_getter_v = is_getter<T>::value; | constexpr decltype(auto) is_getter_v = is_getter<T>::value; | ||||
#endif | |||||
/** | /** | ||||
* @brief Predicate to create new getter objects. | * @brief Predicate to create new getter objects. | ||||
@@ -28,7 +28,8 @@ namespace cppmp | |||||
template<typename T_getter> | template<typename T_getter> | ||||
struct getter_builder< | struct getter_builder< | ||||
list<T_getter>, | list<T_getter>, | ||||
enable_if_t<is_getter_v<decay_t<T_getter>>>> | |||||
enable_if_t<is_getter<decay_t<T_getter>>::value | |||||
>> | |||||
{ | { | ||||
static constexpr decltype(auto) apply(T_getter&& getter) | static constexpr decltype(auto) apply(T_getter&& getter) | ||||
{ return std::forward<T_getter>(getter); } | { return std::forward<T_getter>(getter); } | ||||
@@ -40,7 +41,7 @@ namespace cppmp | |||||
struct getter_builder< | struct getter_builder< | ||||
list<T_value T_object::*>, | list<T_value T_object::*>, | ||||
enable_if_t< | enable_if_t< | ||||
!is_valid_v<lambda_traits<T_value T_object::*>> | |||||
!is_valid<lambda_traits<T_value T_object::*>>::value | |||||
> | > | ||||
> | > | ||||
{ | { | ||||
@@ -54,15 +55,15 @@ namespace cppmp | |||||
member_type member; | member_type member; | ||||
constexpr getter_member_var(member_type p_member) | |||||
inline getter_member_var(member_type p_member) | |||||
: member(p_member) | : member(p_member) | ||||
{ } | { } | ||||
constexpr getter_member_var(getter_member_var&&) = default; | |||||
constexpr getter_member_var(const getter_member_var&) = default; | |||||
inline getter_member_var(getter_member_var&&) = default; | |||||
inline getter_member_var(const getter_member_var&) = default; | |||||
constexpr getter_member_var& operator = (getter_member_var&&) = default; | |||||
constexpr getter_member_var& operator = (const getter_member_var&) = default; | |||||
inline getter_member_var& operator = (getter_member_var&&) = default; | |||||
inline getter_member_var& operator = (const getter_member_var&) = default; | |||||
template<typename X_object> | template<typename X_object> | ||||
constexpr decltype(auto) operator()(X_object&& obj) const | constexpr decltype(auto) operator()(X_object&& obj) const | ||||
@@ -92,15 +93,15 @@ namespace cppmp | |||||
member_type member; | member_type member; | ||||
constexpr getter_member_func(member_type p_member) | |||||
inline getter_member_func(member_type p_member) | |||||
: member(p_member) | : member(p_member) | ||||
{ } | { } | ||||
constexpr getter_member_func(getter_member_func&&) = default; | |||||
constexpr getter_member_func(const getter_member_func&) = default; | |||||
inline getter_member_func(getter_member_func&&) = default; | |||||
inline getter_member_func(const getter_member_func&) = default; | |||||
constexpr getter_member_func& operator = (getter_member_func&&) = default; | |||||
constexpr getter_member_func& operator = (const getter_member_func&) = default; | |||||
inline getter_member_func& operator = (getter_member_func&&) = default; | |||||
inline getter_member_func& operator = (const getter_member_func&) = default; | |||||
template<typename X_object> | template<typename X_object> | ||||
constexpr decltype(auto) operator()(X_object&& obj) const | constexpr decltype(auto) operator()(X_object&& obj) const | ||||
@@ -135,9 +136,11 @@ namespace cppmp | |||||
struct getter_builder< | struct getter_builder< | ||||
list<T_lambda>, | list<T_lambda>, | ||||
enable_if_t< | enable_if_t< | ||||
is_valid_v<lambda_traits<decay_t<T_lambda>>> | |||||
is_valid<lambda_traits<decay_t<T_lambda>>>::value | |||||
&& lambda_traits<decay_t<T_lambda>>::argument_count_v == 1 | && lambda_traits<decay_t<T_lambda>>::argument_count_v == 1 | ||||
&& !is_void_v<typename lambda_traits<decay_t<T_lambda>>::return_type>>> | |||||
&& !is_void<typename lambda_traits<decay_t<T_lambda>>::return_type>::value | |||||
> | |||||
> | |||||
{ | { | ||||
struct getter_lambda | struct getter_lambda | ||||
: public tag_getter | : public tag_getter | ||||
@@ -150,15 +153,15 @@ namespace cppmp | |||||
lambda_type lambda; | lambda_type lambda; | ||||
constexpr getter_lambda(lambda_type&& p_lambda) | |||||
inline getter_lambda(lambda_type&& p_lambda) | |||||
: lambda(std::forward<lambda_type>(p_lambda)) | : lambda(std::forward<lambda_type>(p_lambda)) | ||||
{ } | { } | ||||
constexpr getter_lambda(getter_lambda&&) = default; | |||||
constexpr getter_lambda(const getter_lambda&) = default; | |||||
inline getter_lambda(getter_lambda&&) = default; | |||||
inline getter_lambda(const getter_lambda&) = default; | |||||
constexpr getter_lambda& operator = (getter_lambda&&) = default; | |||||
constexpr getter_lambda& operator = (const getter_lambda&) = default; | |||||
inline getter_lambda& operator = (getter_lambda&&) = default; | |||||
inline getter_lambda& operator = (const getter_lambda&) = default; | |||||
template<typename X_object> | template<typename X_object> | ||||
constexpr decltype(auto) operator()(X_object&& obj) const | constexpr decltype(auto) operator()(X_object&& obj) const | ||||
@@ -177,8 +180,8 @@ namespace cppmp | |||||
struct getter_builder< | struct getter_builder< | ||||
list<T_first, T_second, T_rest...>, | list<T_first, T_second, T_rest...>, | ||||
enable_if_t< | enable_if_t< | ||||
is_valid_v<decltype(make_getter(std::declval<T_first>()))> | |||||
&& is_valid_v<decltype(make_getter(std::declval<T_second>(), std::declval<T_rest>()...))> | |||||
is_valid<decltype(make_getter(std::declval<T_first>()))>::value | |||||
&& is_valid<decltype(make_getter(std::declval<T_second>(), std::declval<T_rest>()...))>::value | |||||
> | > | ||||
> | > | ||||
{ | { | ||||
@@ -194,18 +197,18 @@ namespace cppmp | |||||
first_getter_type first; | first_getter_type first; | ||||
second_getter_type second; | second_getter_type second; | ||||
constexpr getter_chain( | |||||
inline getter_chain( | |||||
first_getter_type&& p_first, | first_getter_type&& p_first, | ||||
second_getter_type&& p_second) | second_getter_type&& p_second) | ||||
: first (std::move(p_first)) | : first (std::move(p_first)) | ||||
, second(std::move(p_second)) | , second(std::move(p_second)) | ||||
{ } | { } | ||||
constexpr getter_chain(getter_chain&&) = default; | |||||
constexpr getter_chain(const getter_chain&) = default; | |||||
inline getter_chain(getter_chain&&) = default; | |||||
inline getter_chain(const getter_chain&) = default; | |||||
constexpr getter_chain& operator = (getter_chain&&) = default; | |||||
constexpr getter_chain& operator = (const getter_chain&) = default; | |||||
inline getter_chain& operator = (getter_chain&&) = default; | |||||
inline getter_chain& operator = (const getter_chain&) = default; | |||||
template<typename X_object> | template<typename X_object> | ||||
constexpr decltype(auto) operator()(X_object&& obj) const | constexpr decltype(auto) operator()(X_object&& obj) const | ||||
@@ -28,11 +28,13 @@ namespace cppmp | |||||
template<typename T> | template<typename T> | ||||
struct is_setter; | struct is_setter; | ||||
#ifdef cppmp_supports_variable_templates | |||||
/** | /** | ||||
* @brief Is true if the passed type is an setter, false otherwise. | * @brief Is true if the passed type is an setter, false otherwise. | ||||
*/ | */ | ||||
template<typename T> | template<typename T> | ||||
constexpr decltype(auto) is_setter_v = is_setter<T>::value; | constexpr decltype(auto) is_setter_v = is_setter<T>::value; | ||||
#endif | |||||
/** | /** | ||||
* @brief Predicate to create new setter objects. | * @brief Predicate to create new setter objects. | ||||
@@ -27,7 +27,8 @@ namespace cppmp | |||||
template<typename T_setter> | template<typename T_setter> | ||||
struct setter_builder< | struct setter_builder< | ||||
list<T_setter>, | list<T_setter>, | ||||
enable_if_t<is_setter_v<decay_t<T_setter>>>> | |||||
enable_if_t<is_setter<decay_t<T_setter>>::value | |||||
>> | |||||
{ | { | ||||
static constexpr decltype(auto) apply(T_setter&& setter) | static constexpr decltype(auto) apply(T_setter&& setter) | ||||
{ return std::forward<T_setter>(setter); } | { return std::forward<T_setter>(setter); } | ||||
@@ -50,15 +51,15 @@ namespace cppmp | |||||
member_type member; | member_type member; | ||||
constexpr setter_member_var(member_type p_member) | |||||
inline setter_member_var(member_type p_member) | |||||
: member(p_member) | : member(p_member) | ||||
{ } | { } | ||||
constexpr setter_member_var(setter_member_var&&) = default; | |||||
constexpr setter_member_var(const setter_member_var&) = default; | |||||
inline setter_member_var(setter_member_var&&) = default; | |||||
inline setter_member_var(const setter_member_var&) = default; | |||||
constexpr setter_member_var& operator = (setter_member_var&&) = default; | |||||
constexpr setter_member_var& operator = (const setter_member_var&) = default; | |||||
inline setter_member_var& operator = (setter_member_var&&) = default; | |||||
inline setter_member_var& operator = (const setter_member_var&) = default; | |||||
template<typename X_object, typename X_value> | template<typename X_object, typename X_value> | ||||
constexpr void operator()(X_object&& obj, X_value&& value) const | constexpr void operator()(X_object&& obj, X_value&& value) const | ||||
@@ -88,15 +89,15 @@ namespace cppmp | |||||
member_type member; | member_type member; | ||||
constexpr setter_member_func(member_type p_member) | |||||
inline setter_member_func(member_type p_member) | |||||
: member(p_member) | : member(p_member) | ||||
{ } | { } | ||||
constexpr setter_member_func(setter_member_func&&) = default; | |||||
constexpr setter_member_func(const setter_member_func&) = default; | |||||
inline setter_member_func(setter_member_func&&) = default; | |||||
inline setter_member_func(const setter_member_func&) = default; | |||||
constexpr setter_member_func& operator = (setter_member_func&&) = default; | |||||
constexpr setter_member_func& operator = (const setter_member_func&) = default; | |||||
inline setter_member_func& operator = (setter_member_func&&) = default; | |||||
inline setter_member_func& operator = (const setter_member_func&) = default; | |||||
template<typename X_object, typename X_value> | template<typename X_object, typename X_value> | ||||
constexpr void operator()(X_object&& obj, X_value&& value) const | constexpr void operator()(X_object&& obj, X_value&& value) const | ||||
@@ -131,7 +132,7 @@ namespace cppmp | |||||
struct setter_builder< | struct setter_builder< | ||||
list<T_lambda>, | list<T_lambda>, | ||||
enable_if_t< | enable_if_t< | ||||
is_valid_v<lambda_traits<decay_t<T_lambda>>> | |||||
is_valid<lambda_traits<decay_t<T_lambda>>>::value | |||||
&& lambda_traits<decay_t<T_lambda>>::argument_count_v == 2>> | && lambda_traits<decay_t<T_lambda>>::argument_count_v == 2>> | ||||
{ | { | ||||
struct setter_lambda | struct setter_lambda | ||||
@@ -145,15 +146,15 @@ namespace cppmp | |||||
lambda_type lambda; | lambda_type lambda; | ||||
constexpr setter_lambda(lambda_type&& p_lambda) | |||||
inline cppmp_constexpr_lambda setter_lambda(lambda_type&& p_lambda) | |||||
: lambda(std::forward<lambda_type>(p_lambda)) | : lambda(std::forward<lambda_type>(p_lambda)) | ||||
{ } | { } | ||||
constexpr setter_lambda(setter_lambda&&) = default; | |||||
constexpr setter_lambda(const setter_lambda&) = default; | |||||
inline cppmp_constexpr_lambda setter_lambda(setter_lambda&&) = default; | |||||
inline cppmp_constexpr_lambda setter_lambda(const setter_lambda&) = default; | |||||
constexpr setter_lambda& operator = (setter_lambda&&) = default; | |||||
constexpr setter_lambda& operator = (const setter_lambda&) = default; | |||||
inline cppmp_constexpr_lambda setter_lambda& operator = (setter_lambda&&) = default; | |||||
inline cppmp_constexpr_lambda setter_lambda& operator = (const setter_lambda&) = default; | |||||
template<typename X_object, typename X_value> | template<typename X_object, typename X_value> | ||||
constexpr void operator()(X_object&& obj, X_value&& value) const | constexpr void operator()(X_object&& obj, X_value&& value) const | ||||
@@ -42,7 +42,11 @@ namespace cppmp | |||||
/* lambda_traits */ | /* lambda_traits */ | ||||
template<typename T_lambda> | template<typename T_lambda> | ||||
struct lambda_traits<T_lambda, enable_if_t<is_valid_v<decltype(&T_lambda::operator())>>> | |||||
struct lambda_traits< | |||||
T_lambda, | |||||
enable_if_t< | |||||
is_valid<decltype(&T_lambda::operator())>::value | |||||
>> | |||||
: public lambda_traits<decltype(&T_lambda::operator())> | : public lambda_traits<decltype(&T_lambda::operator())> | ||||
{ }; | { }; | ||||
@@ -0,0 +1,26 @@ | |||||
#include <cppmp/core/checker.h> | |||||
template<typename X, typename = void> | |||||
struct tpl; | |||||
template<> | |||||
struct tpl<char, void> | |||||
{ | |||||
using is_default = cppmp::true_t; | |||||
}; | |||||
template<> | |||||
struct tpl<int, void> | |||||
{ }; | |||||
static_assert( | |||||
cppmp::is_valid<void>::value, | |||||
"Expected is_valid to be true"); | |||||
static_assert( | |||||
cppmp::is_valid<tpl<int>>::value, | |||||
"Expected is_valid to be true"); | |||||
static_assert( | |||||
!cppmp::is_valid<tpl<float>>::value, | |||||
"Expected is_valid to be false"); |
@@ -0,0 +1,39 @@ | |||||
#include <gtest/gtest.h> | |||||
#include <cppmp/misc/generic_predicate.h> | |||||
template<typename X, typename = void> | |||||
struct builder | |||||
{ | |||||
using is_default = cppmp::true_t; | |||||
template<typename... T_args> | |||||
static constexpr decltype(auto) apply(T_args&&...) | |||||
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for build(...)!"); } | |||||
}; | |||||
template<> | |||||
struct builder< | |||||
cppmp::list<int>, | |||||
void> | |||||
{ | |||||
static constexpr decltype(auto) apply(int i) | |||||
{ return i; } | |||||
}; | |||||
constexpr decltype(auto) build = cppmp::generic_predicate<builder> { }; | |||||
static_assert( | |||||
!decltype(build)::is_valid<void>::value, | |||||
"Expected build to be invalid"); | |||||
static_assert( | |||||
decltype(build)::is_valid<int>::value, | |||||
"Expected build to be valid"); | |||||
TEST(generic_predicate_tests, simple) | |||||
{ | |||||
auto i = build(5); | |||||
EXPECT_EQ(5, i); | |||||
} |
@@ -24,8 +24,9 @@ TEST(cppmp_getter_tests, member_var) | |||||
test_obj o { 1 }; | test_obj o { 1 }; | ||||
auto g = make_getter(&test_obj::value); | auto g = make_getter(&test_obj::value); | ||||
auto i = g(o); | |||||
EXPECT_EQ(1, g(o)); | |||||
EXPECT_EQ(1, i); | |||||
} | } | ||||
TEST(cppmp_getter_tests, member_func) | TEST(cppmp_getter_tests, member_func) | ||||
@@ -33,8 +34,9 @@ TEST(cppmp_getter_tests, member_func) | |||||
test_obj o { 1 }; | test_obj o { 1 }; | ||||
auto g = make_getter(&test_obj::get); | auto g = make_getter(&test_obj::get); | ||||
auto i = g(o); | |||||
EXPECT_EQ(1, g(o)); | |||||
EXPECT_EQ(1, i); | |||||
} | } | ||||
TEST(cppmp_getter_tests, const_member_func) | TEST(cppmp_getter_tests, const_member_func) | ||||
@@ -42,8 +44,9 @@ TEST(cppmp_getter_tests, const_member_func) | |||||
test_obj o { 1 }; | test_obj o { 1 }; | ||||
auto g = make_getter(&test_obj::cget); | auto g = make_getter(&test_obj::cget); | ||||
auto i = g(o); | |||||
EXPECT_EQ(1, g(o)); | |||||
EXPECT_EQ(1, i); | |||||
} | } | ||||
TEST(cppmp_getter_tests, static_func) | TEST(cppmp_getter_tests, static_func) | ||||
@@ -51,8 +54,9 @@ TEST(cppmp_getter_tests, static_func) | |||||
test_obj o { 1 }; | test_obj o { 1 }; | ||||
auto g = make_getter(&test_obj::sget); | auto g = make_getter(&test_obj::sget); | ||||
auto i = g(o); | |||||
EXPECT_EQ(1, g(o)); | |||||
EXPECT_EQ(1, i); | |||||
} | } | ||||
TEST(cppmp_getter_tests, lambda) | TEST(cppmp_getter_tests, lambda) | ||||
@@ -62,6 +66,7 @@ TEST(cppmp_getter_tests, lambda) | |||||
auto g = make_getter([](test_obj& o){ | auto g = make_getter([](test_obj& o){ | ||||
return o.value; | return o.value; | ||||
}); | }); | ||||
auto i = g(obj); | |||||
EXPECT_EQ(1, g(obj)); | |||||
EXPECT_EQ(1, i); | |||||
} | } |
@@ -27,45 +27,45 @@ using type3 = ::cppmp::lambda_traits<std::string(*)(bool)>; | |||||
using type4 = ::cppmp::lambda_traits<decltype(cpp_traits_lambda)>; | using type4 = ::cppmp::lambda_traits<decltype(cpp_traits_lambda)>; | ||||
using type5 = ::cppmp::lambda_traits<decltype(&static_fuu)>; | using type5 = ::cppmp::lambda_traits<decltype(&static_fuu)>; | ||||
static_assert(is_same_v<typename type0::object_type, test_obj>, ""); | |||||
static_assert(is_same_v<typename type0::return_type, int>, ""); | |||||
static_assert(is_same_v<typename type0::arguments_type, std::tuple<int>>, ""); | |||||
static_assert( type0::is_mutable_v == true, ""); | |||||
static_assert( type0::is_static_v == false, ""); | |||||
static_assert( type0::argument_count_v == 1, ""); | |||||
static_assert(is_same<typename type0::object_type, test_obj>::value, ""); | |||||
static_assert(is_same<typename type0::return_type, int>::value, ""); | |||||
static_assert(is_same<typename type0::arguments_type, std::tuple<int>>::value, ""); | |||||
static_assert( type0::is_mutable_v == true, ""); | |||||
static_assert( type0::is_static_v == false, ""); | |||||
static_assert( type0::argument_count_v == 1, ""); | |||||
static_assert(is_same_v<typename type1::object_type, const test_obj>, ""); | |||||
static_assert(is_same_v<typename type1::return_type, double>, ""); | |||||
static_assert(is_same_v<typename type1::arguments_type, std::tuple<float, std::string>>, ""); | |||||
static_assert( type1::is_mutable_v == false, ""); | |||||
static_assert( type1::is_static_v == false, ""); | |||||
static_assert( type1::argument_count_v == 2, ""); | |||||
static_assert(is_same<typename type1::object_type, const test_obj>::value, ""); | |||||
static_assert(is_same<typename type1::return_type, double>::value, ""); | |||||
static_assert(is_same<typename type1::arguments_type, std::tuple<float, std::string>>::value, ""); | |||||
static_assert( type1::is_mutable_v == false, ""); | |||||
static_assert( type1::is_static_v == false, ""); | |||||
static_assert( type1::argument_count_v == 2, ""); | |||||
static_assert(is_same_v<typename type2::object_type, void>, ""); | |||||
static_assert(is_same_v<typename type2::return_type, std::string>, ""); | |||||
static_assert(is_same_v<typename type2::arguments_type, std::tuple<>>, ""); | |||||
static_assert( type2::is_mutable_v == false, ""); | |||||
static_assert( type2::is_static_v == true, ""); | |||||
static_assert( type2::argument_count_v == 0, ""); | |||||
static_assert(is_same<typename type2::object_type, void>::value, ""); | |||||
static_assert(is_same<typename type2::return_type, std::string>::value, ""); | |||||
static_assert(is_same<typename type2::arguments_type, std::tuple<>>::value, ""); | |||||
static_assert( type2::is_mutable_v == false, ""); | |||||
static_assert( type2::is_static_v == true, ""); | |||||
static_assert( type2::argument_count_v == 0, ""); | |||||
static_assert(is_same_v<typename type3::object_type, void>, ""); | |||||
static_assert(is_same_v<typename type3::return_type, std::string>, ""); | |||||
static_assert(is_same_v<typename type3::arguments_type, std::tuple<bool>>, ""); | |||||
static_assert( type3::is_mutable_v == false, ""); | |||||
static_assert( type3::is_static_v == true, ""); | |||||
static_assert( type3::argument_count_v == 1, ""); | |||||
static_assert(is_same<typename type3::object_type, void>::value, ""); | |||||
static_assert(is_same<typename type3::return_type, std::string>::value, ""); | |||||
static_assert(is_same<typename type3::arguments_type, std::tuple<bool>>::value, ""); | |||||
static_assert( type3::is_mutable_v == false, ""); | |||||
static_assert( type3::is_static_v == true, ""); | |||||
static_assert( type3::argument_count_v == 1, ""); | |||||
static_assert(is_same_v<typename type4::return_type, bool>, ""); | |||||
static_assert(is_same_v<typename type4::arguments_type, std::tuple<std::string, int>>, ""); | |||||
static_assert( type4::is_mutable_v == false, ""); | |||||
static_assert( type4::is_static_v == false, ""); | |||||
static_assert( type4::argument_count_v == 2, ""); | |||||
static_assert(is_same<typename type4::return_type, bool>::value, ""); | |||||
static_assert(is_same<typename type4::arguments_type, std::tuple<std::string, int>>::value, ""); | |||||
static_assert( type4::is_mutable_v == false, ""); | |||||
static_assert( type4::is_static_v == false, ""); | |||||
static_assert( type4::argument_count_v == 2, ""); | |||||
static_assert(is_same_v<typename type5::return_type, const test_obj&>, ""); | |||||
static_assert(is_same_v<typename type5::arguments_type, std::tuple<>>, ""); | |||||
static_assert( type5::is_mutable_v == false, ""); | |||||
static_assert( type5::is_static_v == true, ""); | |||||
static_assert( type5::argument_count_v == 0, ""); | |||||
static_assert(is_same<typename type5::return_type, const test_obj&>::value, ""); | |||||
static_assert(is_same<typename type5::arguments_type, std::tuple<>>::value, ""); | |||||
static_assert( type5::is_mutable_v == false, ""); | |||||
static_assert( type5::is_static_v == true, ""); | |||||
static_assert( type5::argument_count_v == 0, ""); | |||||
TEST(cppmp_traits_test, dummy) | TEST(cppmp_traits_test, dummy) | ||||
{ | { | ||||