diff --git a/include/cppmp/config.h b/include/cppmp/config.h new file mode 100644 index 0000000..324337d --- /dev/null +++ b/include/cppmp/config.h @@ -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 diff --git a/include/cppmp/core/checker.h b/include/cppmp/core/checker.h index 6709161..7595806 100644 --- a/include/cppmp/core/checker.h +++ b/include/cppmp/core/checker.h @@ -1,30 +1,45 @@ #pragma once +#include "types.h" +#include "../config.h" + + #define cppmp_define_checker(name) \ template \ struct name \ : public integral_constant::value), std::name::value> \ { }; \ \ - template \ - constexpr decltype(auto) name ## _v = name::value; + cppmp_define_checker_var(name) -#include "types.h" +#ifdef cppmp_supports_variable_templates + #define cppmp_define_checker_var(name) \ + template \ + constexpr decltype(auto) name ## _v = name::value; +#else + #define cppmp_define_checker_var(name) +#endif namespace cppmp { + namespace __impl + { + + template + struct is_valid; + + } + /** * @brief Evaluates to true_t if the passed template parameters are valid, false_t otherwise. */ - template - struct is_valid; + template + struct is_valid + : public __impl::is_valid + { }; - /** - * @brief Is true if the passed template parameters are valid, false otherwise. - */ - template - constexpr decltype(auto) is_valid_v = is_valid::value; + cppmp_define_checker_var(is_valid) /** * @brief Evaluates to true_t if T is a specialization if T_template, false_t otherwise. @@ -32,11 +47,10 @@ namespace cppmp template class T_template> struct is_specialization_of; - /** - * @brief Evaluates to true if T is a specialization if T_template, false otherwise. - */ + #ifdef cppmp_supports_variable_templates template class T_template> constexpr decltype(auto) is_specialization_of_v = is_specialization_of::value; + #endif /** * @brief Evaluates to true_t if all passed parameters are true, false_t otherwise. @@ -44,93 +58,345 @@ namespace cppmp template struct is_true; - /** - * @brief Evaluates to true if all passed parameters are true, false otherwise. - */ + #ifdef cppmp_supports_variable_templates template constexpr decltype(auto) is_true_v = is_true::value; + #endif + + /* primary type categories */ + #ifdef cppmp_std_supports_is_void cppmp_define_checker(is_void); + #endif + + #ifdef cppmp_std_supports_is_null_pointer cppmp_define_checker(is_null_pointer); + #endif + + #ifdef cppmp_std_supports_is_integral cppmp_define_checker(is_integral); + #endif + + #ifdef cppmp_std_supports_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_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); + #endif + + #ifdef cppmp_std_supports_is_lvalue_reference cppmp_define_checker(is_lvalue_reference); + #endif + + #ifdef cppmp_std_supports_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); + #endif + + #ifdef cppmp_std_supports_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_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); + #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_reference); + #endif + + #ifdef cppmp_std_supports_is_member_pointer cppmp_define_checker(is_member_pointer); + #endif + + /* type properties */ + + #ifdef cppmp_std_supports_is_const cppmp_define_checker(is_const); + #endif + + #ifdef cppmp_std_supports_is_volatile cppmp_define_checker(is_volatile); + #endif + + #ifdef cppmp_std_supports_is_trivial cppmp_define_checker(is_trivial); + #endif + + #ifdef cppmp_std_supports_is_trivially_copyable cppmp_define_checker(is_trivially_copyable); + #endif + + #ifdef cppmp_std_supports_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_literal_type); + #endif + + #ifdef cppmp_std_supports_is_empty cppmp_define_checker(is_empty); + #endif + + #ifdef cppmp_std_supports_is_polymorphic cppmp_define_checker(is_polymorphic); + #endif + + #ifdef cppmp_std_supports_is_abstract cppmp_define_checker(is_abstract); + #endif + + #ifdef cppmp_std_supports_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); + #endif + + #ifdef cppmp_std_supports_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_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_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_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_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_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_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_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); + #endif + + #ifdef cppmp_std_supports_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); + #endif + + #ifdef cppmp_std_supports_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); + #endif + + #ifdef cppmp_std_supports_rank cppmp_define_checker(rank); + #endif + + #ifdef cppmp_std_supports_extent cppmp_define_checker(extent); + #endif + + /* type relations */ + + #ifdef cppmp_std_supports_is_same cppmp_define_checker(is_same); + #endif + + #ifdef cppmp_std_supports_is_base_of cppmp_define_checker(is_base_of); + #endif + + #ifdef cppmp_std_supports_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); + #endif + + #ifdef cppmp_std_supports_is_invocable_r cppmp_define_checker(is_invocable_r); + #endif + + #ifdef cppmp_std_supports_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); #endif } #undef cppmp_define_checker +#undef cppmp_define_checker_var #include "checker.inl" diff --git a/include/cppmp/core/checker.inl b/include/cppmp/core/checker.inl index d5af25c..7dac913 100644 --- a/include/cppmp/core/checker.inl +++ b/include/cppmp/core/checker.inl @@ -25,24 +25,24 @@ namespace cppmp : public true_t { }; - } + /* is_valid */ - /* is_valid */ + template + std::true_type is_valid_impl(T *); - template - struct is_valid - : public false_t - { }; + std::false_type is_valid_impl(...); - template - struct is_valid> - : public true_t - { }; + template + struct is_valid + : public decltype(is_valid_impl(std::declval())) + { }; - template<> - struct is_valid - : public true_t - { }; + template<> + struct is_valid + : public true_t + { }; + + } /* is_specialization_of */ diff --git a/include/cppmp/core/constants.h b/include/cppmp/core/constants.h index 694b792..34e8cb3 100644 --- a/include/cppmp/core/constants.h +++ b/include/cppmp/core/constants.h @@ -5,12 +5,6 @@ namespace cppmp { - /** - * @brief Boolean constant value. - */ - template - constexpr bool_t bool_c; - /** * @brief True boolean constant value. */ @@ -21,15 +15,25 @@ namespace cppmp */ 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 + constexpr bool_t bool_c; + /** * @brief Size constant value. */ template constexpr size_t size_c; - /** - * @brief Zero size constant value, - */ - constexpr zero_t zero_c; + #endif } diff --git a/include/cppmp/core/modifier.h b/include/cppmp/core/modifier.h index 4c1b2e5..be37d2c 100644 --- a/include/cppmp/core/modifier.h +++ b/include/cppmp/core/modifier.h @@ -1,5 +1,7 @@ #pragma once +#include + #define cppmp_define_modifier(name) \ template \ struct name \ @@ -18,29 +20,118 @@ namespace cppmp template using decay_t = typename decay::type; - cppmp_define_modifier(remove_cv); + /* const-volatile modifications */ + + #ifdef cppmp_std_supports_remove_const cppmp_define_modifier(remove_const); + #endif + + #ifdef cppmp_std_supports_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); + #endif + + #ifdef cppmp_std_supports_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); + #endif + + #ifdef cppmp_std_supports_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(remove_pointer); - cppmp_define_modifier(add_pointer); + #endif + + /* sign modifications */ + + #ifdef cppmp_std_supports_make_signed cppmp_define_modifier(make_signed); + #endif + + #ifdef cppmp_std_supports_make_unsigned cppmp_define_modifier(make_unsigned); + #endif + + /* array modifications */ + + #ifdef cppmp_std_supports_remove_extent cppmp_define_modifier(remove_extent); + #endif + + #ifdef cppmp_std_supports_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); + #endif + + #ifdef cppmp_std_supports_underlying_type cppmp_define_modifier(underlying_type); + #endif + + #ifdef cppmp_std_supports_result_of cppmp_define_modifier(result_of); + #endif - #if __cplusplus >= 201703L + #ifdef cppmp_std_supports_invoke_result cppmp_define_modifier(invoke_result); #endif + #ifdef cppmp_std_supports_aligned_storage + template + struct aligned_storage + : public std::aligned_storage + { }; + + template + using aligned_storage_t = typename aligned_storage::type; + #endif + + #ifdef cppmp_std_supports_aligned_union + template + struct aligned_union + : public std::aligned_union + { }; + + template + using aligned_union_t = typename aligned_union::type; + #endif + } #undef cppmp_define_modifier diff --git a/include/cppmp/core/types.h b/include/cppmp/core/types.h index 5dffd96..4f2f8ff 100644 --- a/include/cppmp/core/types.h +++ b/include/cppmp/core/types.h @@ -1,5 +1,6 @@ #pragma once +#include #include namespace cppmp @@ -18,8 +19,10 @@ namespace cppmp struct type_t { }; + #ifdef cppmp_supports_variable_templates template constexpr decltype(auto) type_v = type_t { }; + #endif /** * @brief Simple type list. diff --git a/include/cppmp/misc/generic_predicate.h b/include/cppmp/misc/generic_predicate.h index eb907bf..0aec78f 100644 --- a/include/cppmp/misc/generic_predicate.h +++ b/include/cppmp/misc/generic_predicate.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -8,16 +9,19 @@ namespace cppmp namespace __impl { + template + struct is_default_impl + { + private: + template + static void impl(decltype(typename X::is_default(), int())); - template - struct is_valid_builder - : public cppmp::true_t - { }; + template + static bool impl(char); - template - struct is_valid_builder> - : public cppmp::false_t - { }; + public: + static const bool value = std::is_same(0))>::value; + }; } @@ -34,14 +38,16 @@ namespace cppmp */ template struct is_valid - : public __impl::is_valid_builder>> + : public bool_t>>::value> { }; + #ifdef cppmp_supports_variable_templates /** * @brief Evaluates to true if the passed arguments would create a valid object, false otherwise. */ template static constexpr bool is_valid_v = is_valid::value; + #endif /** * @brief Invoke the builder to create the requested object. diff --git a/include/cppmp/misc/getter.h b/include/cppmp/misc/getter.h index 240898b..0e40242 100644 --- a/include/cppmp/misc/getter.h +++ b/include/cppmp/misc/getter.h @@ -29,11 +29,13 @@ namespace cppmp template struct is_getter; + #ifdef cppmp_supports_variable_templates /** * @brief Is true if the passed type is an getter, false otherwise. */ template constexpr decltype(auto) is_getter_v = is_getter::value; + #endif /** * @brief Predicate to create new getter objects. diff --git a/include/cppmp/misc/getter.inl b/include/cppmp/misc/getter.inl index b305abd..24ce87d 100644 --- a/include/cppmp/misc/getter.inl +++ b/include/cppmp/misc/getter.inl @@ -28,7 +28,8 @@ namespace cppmp template struct getter_builder< list, - enable_if_t>>> + enable_if_t>::value + >> { static constexpr decltype(auto) apply(T_getter&& getter) { return std::forward(getter); } @@ -40,7 +41,7 @@ namespace cppmp struct getter_builder< list, enable_if_t< - !is_valid_v> + !is_valid>::value > > { @@ -54,15 +55,15 @@ namespace cppmp member_type member; - constexpr getter_member_var(member_type p_member) + inline getter_member_var(member_type 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 constexpr decltype(auto) operator()(X_object&& obj) const @@ -92,15 +93,15 @@ namespace cppmp member_type member; - constexpr getter_member_func(member_type p_member) + inline getter_member_func(member_type 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 constexpr decltype(auto) operator()(X_object&& obj) const @@ -135,9 +136,11 @@ namespace cppmp struct getter_builder< list, enable_if_t< - is_valid_v>> + is_valid>>::value && lambda_traits>::argument_count_v == 1 - && !is_void_v>::return_type>>> + && !is_void>::return_type>::value + > + > { struct getter_lambda : public tag_getter @@ -150,15 +153,15 @@ namespace cppmp lambda_type lambda; - constexpr getter_lambda(lambda_type&& p_lambda) + inline getter_lambda(lambda_type&& p_lambda) : lambda(std::forward(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 constexpr decltype(auto) operator()(X_object&& obj) const @@ -177,8 +180,8 @@ namespace cppmp struct getter_builder< list, enable_if_t< - is_valid_v()))> - && is_valid_v(), std::declval()...))> + is_valid()))>::value + && is_valid(), std::declval()...))>::value > > { @@ -194,18 +197,18 @@ namespace cppmp first_getter_type first; second_getter_type second; - constexpr getter_chain( + inline getter_chain( first_getter_type&& p_first, second_getter_type&& p_second) : first (std::move(p_first)) , 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 constexpr decltype(auto) operator()(X_object&& obj) const diff --git a/include/cppmp/misc/setter.h b/include/cppmp/misc/setter.h index ab4a9f4..24e0333 100644 --- a/include/cppmp/misc/setter.h +++ b/include/cppmp/misc/setter.h @@ -28,11 +28,13 @@ namespace cppmp template struct is_setter; + #ifdef cppmp_supports_variable_templates /** * @brief Is true if the passed type is an setter, false otherwise. */ template constexpr decltype(auto) is_setter_v = is_setter::value; + #endif /** * @brief Predicate to create new setter objects. diff --git a/include/cppmp/misc/setter.inl b/include/cppmp/misc/setter.inl index c4ef1fc..fafdd76 100644 --- a/include/cppmp/misc/setter.inl +++ b/include/cppmp/misc/setter.inl @@ -27,7 +27,8 @@ namespace cppmp template struct setter_builder< list, - enable_if_t>>> + enable_if_t>::value + >> { static constexpr decltype(auto) apply(T_setter&& setter) { return std::forward(setter); } @@ -50,15 +51,15 @@ namespace cppmp member_type member; - constexpr setter_member_var(member_type p_member) + inline setter_member_var(member_type 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 constexpr void operator()(X_object&& obj, X_value&& value) const @@ -88,15 +89,15 @@ namespace cppmp member_type member; - constexpr setter_member_func(member_type p_member) + inline setter_member_func(member_type 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 constexpr void operator()(X_object&& obj, X_value&& value) const @@ -131,7 +132,7 @@ namespace cppmp struct setter_builder< list, enable_if_t< - is_valid_v>> + is_valid>>::value && lambda_traits>::argument_count_v == 2>> { struct setter_lambda @@ -145,15 +146,15 @@ namespace cppmp lambda_type lambda; - constexpr setter_lambda(lambda_type&& p_lambda) + inline cppmp_constexpr_lambda setter_lambda(lambda_type&& p_lambda) : lambda(std::forward(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 constexpr void operator()(X_object&& obj, X_value&& value) const diff --git a/include/cppmp/traits/lambda_traits.inl b/include/cppmp/traits/lambda_traits.inl index ea1d1d6..8d71af2 100644 --- a/include/cppmp/traits/lambda_traits.inl +++ b/include/cppmp/traits/lambda_traits.inl @@ -42,7 +42,11 @@ namespace cppmp /* lambda_traits */ template - struct lambda_traits>> + struct lambda_traits< + T_lambda, + enable_if_t< + is_valid::value + >> : public lambda_traits { }; diff --git a/test/cppmp/cppmp_checker_tests.cpp b/test/cppmp/cppmp_checker_tests.cpp new file mode 100644 index 0000000..bcda3f4 --- /dev/null +++ b/test/cppmp/cppmp_checker_tests.cpp @@ -0,0 +1,26 @@ +#include + +template +struct tpl; + +template<> +struct tpl +{ + using is_default = cppmp::true_t; +}; + +template<> +struct tpl + { }; + +static_assert( + cppmp::is_valid::value, + "Expected is_valid to be true"); + +static_assert( + cppmp::is_valid>::value, + "Expected is_valid to be true"); + +static_assert( + !cppmp::is_valid>::value, + "Expected is_valid to be false"); diff --git a/test/cppmp/cppmp_generic_predicate_tests.cpp b/test/cppmp/cppmp_generic_predicate_tests.cpp new file mode 100644 index 0000000..12fdd55 --- /dev/null +++ b/test/cppmp/cppmp_generic_predicate_tests.cpp @@ -0,0 +1,39 @@ +#include + +#include + +template +struct builder +{ + using is_default = cppmp::true_t; + + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for build(...)!"); } +}; + +template<> +struct builder< + cppmp::list, + void> +{ + static constexpr decltype(auto) apply(int i) + { return i; } +}; + +constexpr decltype(auto) build = cppmp::generic_predicate { }; + +static_assert( + !decltype(build)::is_valid::value, + "Expected build to be invalid"); + +static_assert( + decltype(build)::is_valid::value, + "Expected build to be valid"); + +TEST(generic_predicate_tests, simple) +{ + auto i = build(5); + + EXPECT_EQ(5, i); +} diff --git a/test/cppmp/cppmp_getter_tests.cpp b/test/cppmp/cppmp_getter_tests.cpp index cfa9302..3d935bb 100644 --- a/test/cppmp/cppmp_getter_tests.cpp +++ b/test/cppmp/cppmp_getter_tests.cpp @@ -24,8 +24,9 @@ TEST(cppmp_getter_tests, member_var) test_obj o { 1 }; 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) @@ -33,8 +34,9 @@ TEST(cppmp_getter_tests, member_func) test_obj o { 1 }; 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) @@ -42,8 +44,9 @@ TEST(cppmp_getter_tests, const_member_func) test_obj o { 1 }; 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) @@ -51,8 +54,9 @@ TEST(cppmp_getter_tests, static_func) test_obj o { 1 }; 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) @@ -62,6 +66,7 @@ TEST(cppmp_getter_tests, lambda) auto g = make_getter([](test_obj& o){ return o.value; }); + auto i = g(obj); - EXPECT_EQ(1, g(obj)); + EXPECT_EQ(1, i); } diff --git a/test/cppmp/cppmp_traits_test.cpp b/test/cppmp/cppmp_traits_test.cpp index abe0f86..cd0a666 100644 --- a/test/cppmp/cppmp_traits_test.cpp +++ b/test/cppmp/cppmp_traits_test.cpp @@ -27,45 +27,45 @@ using type3 = ::cppmp::lambda_traits; using type4 = ::cppmp::lambda_traits; using type5 = ::cppmp::lambda_traits; -static_assert(is_same_v, ""); -static_assert(is_same_v, ""); -static_assert(is_same_v>, ""); -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::value, ""); +static_assert(is_same::value, ""); +static_assert(is_same>::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, ""); -static_assert(is_same_v, ""); -static_assert(is_same_v>, ""); -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::value, ""); +static_assert(is_same::value, ""); +static_assert(is_same>::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, ""); -static_assert(is_same_v, ""); -static_assert(is_same_v>, ""); -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::value, ""); +static_assert(is_same::value, ""); +static_assert(is_same>::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, ""); -static_assert(is_same_v, ""); -static_assert(is_same_v>, ""); -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::value, ""); +static_assert(is_same::value, ""); +static_assert(is_same>::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, ""); -static_assert(is_same_v>, ""); -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::value, ""); +static_assert(is_same>::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, ""); -static_assert(is_same_v>, ""); -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::value, ""); +static_assert(is_same>::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) {