* Implemented miscellaneous features (generic predicate, getter, setter) * Implemented traits features (lambda traits)master
| @@ -1,3 +1,5 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <cppmp/dummy.h> | |||||
| #include "cppmp/core.h" | |||||
| #include "cppmp/misc.h" | |||||
| #include "cppmp/traits.h" | |||||
| @@ -0,0 +1,7 @@ | |||||
| #pragma once | |||||
| #include "core/checker.h" | |||||
| #include "core/conditionals.h" | |||||
| #include "core/constants.h" | |||||
| #include "core/modifier.h" | |||||
| #include "core/types.h" | |||||
| @@ -0,0 +1,133 @@ | |||||
| #pragma once | |||||
| #define cppmp_define_checker(name) \ | |||||
| template<typename... T> \ | |||||
| struct name \ | |||||
| : public integral_constant<decltype(std::name<T...>::value), std::name<T...>::value> \ | |||||
| { }; \ | |||||
| \ | |||||
| template<typename... T> \ | |||||
| constexpr decltype(auto) name ## _v = name<T...>::value; | |||||
| #include "types.h" | |||||
| namespace cppmp | |||||
| { | |||||
| /** | |||||
| * @brief Evaluates to true_t if the passed template parameters are valid, false_t otherwise. | |||||
| */ | |||||
| template<typename...> | |||||
| struct is_valid; | |||||
| /** | |||||
| * @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; | |||||
| /** | |||||
| * @brief Evaluates to true_t if T is a specialization if T_template, false_t otherwise. | |||||
| */ | |||||
| template<typename T, template <typename...> class T_template> | |||||
| struct is_specialization_of; | |||||
| /** | |||||
| * @brief Evaluates to true if T is a specialization if T_template, false otherwise. | |||||
| */ | |||||
| template<typename T, template <typename...> class T_template> | |||||
| constexpr decltype(auto) is_specialization_of_v = is_specialization_of<T, T_template>::value; | |||||
| /** | |||||
| * @brief Evaluates to true_t if all passed parameters are true, false_t otherwise. | |||||
| */ | |||||
| template<bool... B> | |||||
| struct is_true; | |||||
| /** | |||||
| * @brief Evaluates to true if all passed parameters are true, false otherwise. | |||||
| */ | |||||
| template<bool... B> | |||||
| constexpr decltype(auto) is_true_v = is_true<B...>::value; | |||||
| cppmp_define_checker(is_void); | |||||
| cppmp_define_checker(is_null_pointer); | |||||
| cppmp_define_checker(is_integral); | |||||
| cppmp_define_checker(is_floating_point); | |||||
| 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); | |||||
| cppmp_define_checker(is_pointer); | |||||
| cppmp_define_checker(is_lvalue_reference); | |||||
| cppmp_define_checker(is_rvalue_reference); | |||||
| cppmp_define_checker(is_member_object_pointer); | |||||
| cppmp_define_checker(is_member_function_pointer); | |||||
| cppmp_define_checker(is_fundamental); | |||||
| cppmp_define_checker(is_arithmetic); | |||||
| cppmp_define_checker(is_scalar); | |||||
| cppmp_define_checker(is_object); | |||||
| cppmp_define_checker(is_compound); | |||||
| cppmp_define_checker(is_reference); | |||||
| cppmp_define_checker(is_member_pointer); | |||||
| cppmp_define_checker(is_const); | |||||
| cppmp_define_checker(is_volatile); | |||||
| cppmp_define_checker(is_trivial); | |||||
| cppmp_define_checker(is_trivially_copyable); | |||||
| cppmp_define_checker(is_standard_layout); | |||||
| cppmp_define_checker(is_pod); | |||||
| cppmp_define_checker(is_literal_type); | |||||
| cppmp_define_checker(has_unique_object_representations); | |||||
| cppmp_define_checker(is_empty); | |||||
| cppmp_define_checker(is_polymorphic); | |||||
| cppmp_define_checker(is_abstract); | |||||
| cppmp_define_checker(is_final); | |||||
| cppmp_define_checker(is_aggregate); | |||||
| cppmp_define_checker(is_signed); | |||||
| cppmp_define_checker(is_unsigned); | |||||
| cppmp_define_checker(is_constructible); | |||||
| cppmp_define_checker(is_trivially_constructible); | |||||
| cppmp_define_checker(is_nothrow_constructible); | |||||
| cppmp_define_checker(is_default_constructible); | |||||
| cppmp_define_checker(is_trivially_default_constructible); | |||||
| cppmp_define_checker(is_nothrow_default_constructible); | |||||
| cppmp_define_checker(is_copy_constructible); | |||||
| cppmp_define_checker(is_trivially_copy_constructible); | |||||
| cppmp_define_checker(is_nothrow_copy_constructible); | |||||
| cppmp_define_checker(is_move_constructible); | |||||
| cppmp_define_checker(is_trivially_move_constructible); | |||||
| cppmp_define_checker(is_nothrow_move_constructible); | |||||
| cppmp_define_checker(is_assignable); | |||||
| cppmp_define_checker(is_trivially_assignable); | |||||
| cppmp_define_checker(is_nothrow_assignable); | |||||
| cppmp_define_checker(is_copy_assignable); | |||||
| cppmp_define_checker(is_trivially_copy_assignable); | |||||
| cppmp_define_checker(is_nothrow_copy_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); | |||||
| cppmp_define_checker(is_swappable_with); | |||||
| cppmp_define_checker(is_swappable); | |||||
| cppmp_define_checker(is_nothrow_swappable_with); | |||||
| cppmp_define_checker(is_nothrow_swappable); | |||||
| cppmp_define_checker(alignment_of); | |||||
| cppmp_define_checker(rank); | |||||
| cppmp_define_checker(extent); | |||||
| cppmp_define_checker(is_same); | |||||
| cppmp_define_checker(is_base_of); | |||||
| cppmp_define_checker(is_convertible); | |||||
| cppmp_define_checker(is_invocable); | |||||
| cppmp_define_checker(is_invocable_r); | |||||
| cppmp_define_checker(is_nothrow_invocable); | |||||
| cppmp_define_checker(is_nothrow_invocable_r); | |||||
| } | |||||
| #undef cppmp_define_checker | |||||
| #include "checker.inl" | |||||
| @@ -0,0 +1,51 @@ | |||||
| #pragma once | |||||
| #include "checker.h" | |||||
| namespace cppmp | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* bool_pack */ | |||||
| template<bool...> | |||||
| struct bool_pack; | |||||
| /* is_specialization_of_impl */ | |||||
| template<typename T, template <typename...> class T_template> | |||||
| struct is_specialization_of_impl | |||||
| : public false_t | |||||
| { }; | |||||
| template<template <typename...> class T_template, typename... Ts> | |||||
| struct is_specialization_of_impl<T_template<Ts...>, T_template> | |||||
| : public true_t | |||||
| { }; | |||||
| } | |||||
| /* is_valid */ | |||||
| template<typename...> | |||||
| struct is_valid | |||||
| : public true_t | |||||
| { }; | |||||
| /* is_specialization_of */ | |||||
| template<typename T, template <typename...> class T_template> | |||||
| struct is_specialization_of | |||||
| : public __impl::is_specialization_of_impl<T, T_template> | |||||
| { }; | |||||
| /* is_true */ | |||||
| template<bool... B> | |||||
| struct is_true | |||||
| : public is_same<__impl::bool_pack<true, B...>, __impl::bool_pack<B..., true>> | |||||
| { }; | |||||
| } | |||||
| @@ -0,0 +1,142 @@ | |||||
| #pragma once | |||||
| #include "types.h" | |||||
| namespace cppmp | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* eval_if_c_impl */ | |||||
| template<bool B, typename T, template<typename...> class E, typename... A> | |||||
| struct eval_if_impl; | |||||
| } | |||||
| /* enable_if */ | |||||
| /** | |||||
| * @brief Defines T as ::type if B is true, otherwise the resulting type is empty. | |||||
| */ | |||||
| template<bool B, typename T = void> | |||||
| struct enable_if | |||||
| : public std::enable_if<B, T> | |||||
| { }; | |||||
| /** | |||||
| * @brief Resulting type is T if B is true. If B is false the resulting type is invalid. | |||||
| */ | |||||
| template<bool B, typename T = void> | |||||
| using enable_if_t = typename enable_if<B, T>::type; | |||||
| /* conditional/if */ | |||||
| /** | |||||
| * @brief Defines T as ::type if B is true, F otherwise. | |||||
| */ | |||||
| template<bool B, typename T, typename F> | |||||
| struct conditional | |||||
| : public std::conditional<B, T, F> | |||||
| { }; | |||||
| /** | |||||
| * @brief Evaluates to T if B is true, to F otherwise. | |||||
| */ | |||||
| template<bool B, typename T, typename F> | |||||
| using conditional_t = typename conditional<B, T, F>::type; | |||||
| /** | |||||
| * @brief Same as conditional. | |||||
| */ | |||||
| template<bool B, typename T, typename F> | |||||
| struct if_ | |||||
| : public conditional<B, T, F> | |||||
| { }; | |||||
| /** | |||||
| * @brief Same as conditional_t. | |||||
| */ | |||||
| template<bool B, typename T, typename F> | |||||
| using if_t = typename if_<B, T, F>::type; | |||||
| /* eval_if */ | |||||
| /** | |||||
| * @brief Defines T as ::type if B is true, evaluates E<A...> otherwise. | |||||
| */ | |||||
| template<bool B, typename T, template<typename...> class E, typename... A> | |||||
| struct eval_if | |||||
| : public __impl::eval_if_impl<B, T, E, A...> | |||||
| { }; | |||||
| /** | |||||
| * @brief Evaluates to T if B is true, to E<A...> otherwise. | |||||
| */ | |||||
| template<bool B, typename T, template<typename...> class E, typename... A> | |||||
| using eval_if_t = typename eval_if<B, T, E, A...>::type; | |||||
| /* conjunction/and */ | |||||
| /** | |||||
| * @brief Evaluates to true_t if all passed arguments are also true_t. | |||||
| */ | |||||
| template<typename... T> | |||||
| struct conjunction | |||||
| : public std::conjunction<T...> | |||||
| { }; | |||||
| /** | |||||
| * @brief It to true if all passed arguments are also true_t. | |||||
| */ | |||||
| template<typename... T> | |||||
| constexpr decltype(auto) conjunction_v = conjunction<T...>::value; | |||||
| /** | |||||
| * @brief Same as conjunction. | |||||
| */ | |||||
| template<typename... T> | |||||
| struct and_ | |||||
| : public conjunction<T...> | |||||
| { }; | |||||
| /** | |||||
| * @brief Same as conjunction_v. | |||||
| */ | |||||
| template<typename... T> | |||||
| constexpr decltype(auto) and_v = conjunction<T...>::value; | |||||
| /* disjunction/or */ | |||||
| /** | |||||
| * @brief Evaluates to true_t if at least one passed arguments is true_t. | |||||
| */ | |||||
| template<typename... T> | |||||
| struct disjunction | |||||
| : public std::disjunction<T...> | |||||
| { }; | |||||
| /** | |||||
| * @brief Is true if at least one passed arguments is true_t. | |||||
| */ | |||||
| template<typename... T> | |||||
| constexpr decltype(auto) disjunction_v = disjunction<T...>::value; | |||||
| /** | |||||
| * @brief Same as disjunction. | |||||
| */ | |||||
| template<typename... T> | |||||
| struct or_ | |||||
| : public disjunction<T...> | |||||
| { }; | |||||
| /** | |||||
| * @brief Same as disjunction_v. | |||||
| */ | |||||
| template<typename... T> | |||||
| constexpr decltype(auto) or_v = disjunction<T...>::value; | |||||
| } | |||||
| #include "conditionals.inl" | |||||
| @@ -0,0 +1,23 @@ | |||||
| #pragma once | |||||
| #include "conditionals.h" | |||||
| namespace cppmp | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* eval_if_impl */ | |||||
| template<typename T, template<typename...> class E, typename... A> | |||||
| struct eval_if_impl<true, T, E, A...> | |||||
| { using type = T; }; | |||||
| template<typename T, template<typename...> class E, typename... A> | |||||
| struct eval_if_impl<false, T, E, A...> | |||||
| { using type = E<A...>; }; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,35 @@ | |||||
| #pragma onec | |||||
| #include "types.h" | |||||
| namespace cppmp | |||||
| { | |||||
| /** | |||||
| * @brief Boolean constant value. | |||||
| */ | |||||
| template<bool B> | |||||
| constexpr bool_t<B> bool_c; | |||||
| /** | |||||
| * @brief True boolean constant value. | |||||
| */ | |||||
| constexpr true_t true_c; | |||||
| /** | |||||
| * @brief False boolean constant value. | |||||
| */ | |||||
| constexpr false_t false_c; | |||||
| /** | |||||
| * @brief Size constant value. | |||||
| */ | |||||
| template<std::size_t I> | |||||
| constexpr size_t<I> size_c; | |||||
| /** | |||||
| * @brief Zero size constant value, | |||||
| */ | |||||
| constexpr zero_t zero_c; | |||||
| } | |||||
| @@ -0,0 +1,45 @@ | |||||
| #pragma once | |||||
| #define cppmp_define_modifier(name) \ | |||||
| template<typename... T> \ | |||||
| struct name \ | |||||
| : public std::name<T...> \ | |||||
| { }; \ | |||||
| \ | |||||
| template<typename... T> \ | |||||
| using name ## _t = typename name<T...>::type | |||||
| namespace cppmp | |||||
| { | |||||
| template<class T> | |||||
| struct decay; | |||||
| template<typename T> | |||||
| using decay_t = typename decay<T>::type; | |||||
| cppmp_define_modifier(remove_cv); | |||||
| cppmp_define_modifier(remove_const); | |||||
| cppmp_define_modifier(remove_volatile); | |||||
| cppmp_define_modifier(add_cv); | |||||
| cppmp_define_modifier(add_const); | |||||
| cppmp_define_modifier(add_volatile); | |||||
| cppmp_define_modifier(remove_reference); | |||||
| cppmp_define_modifier(add_lvalue_reference); | |||||
| cppmp_define_modifier(add_rvalue_reference); | |||||
| cppmp_define_modifier(remove_pointer); | |||||
| cppmp_define_modifier(add_pointer); | |||||
| cppmp_define_modifier(make_signed); | |||||
| cppmp_define_modifier(make_unsigned); | |||||
| cppmp_define_modifier(remove_extent); | |||||
| cppmp_define_modifier(remove_all_extents); | |||||
| cppmp_define_modifier(common_type); | |||||
| cppmp_define_modifier(underlying_type); | |||||
| cppmp_define_modifier(result_of); | |||||
| cppmp_define_modifier(invoke_result); | |||||
| } | |||||
| #undef cppmp_define_modifier | |||||
| #include "modifier.inl" | |||||
| @@ -0,0 +1,39 @@ | |||||
| #pragma once | |||||
| #include "modifier.h" | |||||
| namespace cppmp | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* decay_impl */ | |||||
| template <typename T, typename U = remove_reference_t<T>> | |||||
| struct decay_impl | |||||
| { using type = remove_cv_t<U>; }; | |||||
| template <typename T, typename U> | |||||
| struct decay_impl<T, U[]> | |||||
| { using type = U*; }; | |||||
| template <typename T, typename U, std::size_t N> | |||||
| struct decay_impl<T, U[N]> | |||||
| { using type = U*; }; | |||||
| template <typename T, typename R, typename ...A> | |||||
| struct decay_impl<T, R(A...)> | |||||
| { using type = R(*)(A...); }; | |||||
| template <typename T, typename R, typename ...A> | |||||
| struct decay_impl<T, R(A..., ...)> | |||||
| { using type = R(*)(A..., ...); }; | |||||
| } | |||||
| template<class T> | |||||
| struct decay | |||||
| : public __impl::decay_impl<T> | |||||
| { }; | |||||
| } | |||||
| @@ -0,0 +1,74 @@ | |||||
| #pragma once | |||||
| #include <type_traits> | |||||
| namespace cppmp | |||||
| { | |||||
| /** | |||||
| * @brief Evaluates to void. | |||||
| */ | |||||
| template<typename...> | |||||
| using void_t = void; | |||||
| /** | |||||
| * @brief Simple type list. | |||||
| */ | |||||
| template<typename...> | |||||
| struct list | |||||
| { }; | |||||
| /** | |||||
| * @brief Inherit from all passed types. | |||||
| */ | |||||
| template<typename... T> | |||||
| struct inherit | |||||
| : public T... | |||||
| { }; | |||||
| /** | |||||
| * @brief Type to wrap constant values at compile time. | |||||
| */ | |||||
| template<typename T, T t> | |||||
| struct integral_constant | |||||
| : public std::integral_constant<T, t> | |||||
| { }; | |||||
| /** | |||||
| * @brief Boolean constant type. | |||||
| */ | |||||
| template<bool B> | |||||
| struct bool_t | |||||
| : public integral_constant<bool, B> | |||||
| { }; | |||||
| /** | |||||
| * @brief True boolean constant type. | |||||
| */ | |||||
| struct true_t | |||||
| : public bool_t<true> | |||||
| { }; | |||||
| /** | |||||
| * @brief False boolean constant type. | |||||
| */ | |||||
| struct false_t | |||||
| : public bool_t<false> | |||||
| { }; | |||||
| /** | |||||
| * @brief Size contant type. | |||||
| */ | |||||
| template<size_t S> | |||||
| struct size_t | |||||
| : public integral_constant<std::size_t, S> | |||||
| { }; | |||||
| /** | |||||
| * @brief Zero zize constant type. | |||||
| */ | |||||
| struct zero_t | |||||
| : public size_t<0> | |||||
| { }; | |||||
| } | |||||
| @@ -1,13 +0,0 @@ | |||||
| #pragma once | |||||
| #include <string> | |||||
| namespace cppmp | |||||
| { | |||||
| struct Dummy | |||||
| { | |||||
| static std::string getHelloWorld(); | |||||
| }; | |||||
| } | |||||
| @@ -0,0 +1,5 @@ | |||||
| #pragma once | |||||
| #include "misc/generic_predicate.h" | |||||
| #include "misc/getter.h" | |||||
| #include "misc/setter.h" | |||||
| @@ -0,0 +1,26 @@ | |||||
| #pragma once | |||||
| namespace cppmp | |||||
| { | |||||
| /** | |||||
| * @brief Helper class to create generic predicates. | |||||
| * | |||||
| * @tparam T_builder Builder class to pass arguments to. | |||||
| */ | |||||
| template<template<typename...> class T_builder> | |||||
| struct generic_predicate | |||||
| { | |||||
| /** | |||||
| * @brief Invoke the builder to create the requested object. | |||||
| * | |||||
| * @param args Arguments to pass to the builder. | |||||
| * | |||||
| * @return Object created from the builder. | |||||
| */ | |||||
| template<typename... T_args> | |||||
| constexpr decltype(auto) operator()(T_args&&... args) const | |||||
| { return T_builder<list<T_args...>>::apply(std::forward<T_args>(args)...); } | |||||
| }; | |||||
| } | |||||
| @@ -0,0 +1,41 @@ | |||||
| #pragma once | |||||
| #include "generic_predicate.h" | |||||
| namespace cppmp | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* tag_getter */ | |||||
| struct tag_getter; | |||||
| /* getter_builder */ | |||||
| template<typename X, typename = void> | |||||
| struct getter_builder; | |||||
| } | |||||
| /** | |||||
| * @brief Evaluates to true_t if the passed type is an getter, to false_t otherwise. | |||||
| */ | |||||
| template<typename T> | |||||
| struct is_getter; | |||||
| /** | |||||
| * @brief Is true if the passed type is an getter, false otherwise. | |||||
| */ | |||||
| template<typename T> | |||||
| constexpr decltype(auto) is_getter_v = is_getter<T>::value; | |||||
| /** | |||||
| * @brief Predicate to create new getter objects. | |||||
| */ | |||||
| constexpr decltype(auto) make_getter = generic_predicate<__impl::getter_builder> { }; | |||||
| } | |||||
| #include "getter.inl" | |||||
| @@ -0,0 +1,179 @@ | |||||
| #pragma once | |||||
| #include <cppmp/traits/lambda_traits.h> | |||||
| #include "getter.h" | |||||
| namespace cppmp | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* tag_getter */ | |||||
| struct tag_getter | |||||
| { }; | |||||
| /* getter_builder - default */ | |||||
| template<typename X, typename> | |||||
| struct getter_builder | |||||
| { | |||||
| template<typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&...) | |||||
| { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_getter(...)!"); } | |||||
| }; | |||||
| /* getter_builder - redirect existing getter */ | |||||
| template<typename T_getter> | |||||
| struct getter_builder< | |||||
| list<T_getter>, | |||||
| enable_if_t<is_getter_v<decay_t<T_getter>>>> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_getter&& getter) | |||||
| { return std::forward<T_getter>(getter); } | |||||
| }; | |||||
| /* getter_builder - member variable */ | |||||
| template<typename T_object, typename T_value> | |||||
| struct getter_builder< | |||||
| list<T_value T_object::*>, | |||||
| void> | |||||
| { | |||||
| struct getter_member_var | |||||
| : public tag_getter | |||||
| { | |||||
| using object_type = T_object; | |||||
| using value_type = T_value; | |||||
| using member_type = value_type object_type::*; | |||||
| member_type member; | |||||
| constexpr 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; | |||||
| constexpr getter_member_var& operator = (getter_member_var&&) = default; | |||||
| constexpr getter_member_var& operator = (const getter_member_var&) = default; | |||||
| template<typename X_object> | |||||
| constexpr decltype(auto) operator()(X_object&& obj) const | |||||
| { return std::forward<X_object>(obj).*member; } | |||||
| }; | |||||
| using object_type = T_object; | |||||
| using value_type = T_value; | |||||
| using member_type = value_type object_type::*; | |||||
| static constexpr decltype(auto) apply(member_type&& getter) | |||||
| { return getter_member_var(std::forward<member_type>(getter)); } | |||||
| }; | |||||
| /* getter_builder - member function */ | |||||
| template<typename T_object, typename T_value, typename T_member> | |||||
| struct getter_builder_member_func | |||||
| { | |||||
| struct getter_member_func | |||||
| : public tag_getter | |||||
| { | |||||
| using object_type = T_object; | |||||
| using value_type = T_value; | |||||
| using member_type = T_member; | |||||
| member_type member; | |||||
| constexpr 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; | |||||
| constexpr getter_member_func& operator = (getter_member_func&&) = default; | |||||
| constexpr getter_member_func& operator = (const getter_member_func&) = default; | |||||
| template<typename X_object> | |||||
| constexpr decltype(auto) operator()(X_object&& obj) const | |||||
| { return (std::forward<X_object>(obj).*member)(); } | |||||
| }; | |||||
| using object_type = T_object; | |||||
| using value_type = T_value; | |||||
| using member_type = T_member; | |||||
| static constexpr decltype(auto) apply(member_type&& getter) | |||||
| { return getter_member_func(std::forward<member_type>(getter)); } | |||||
| }; | |||||
| template<typename T_object, typename T_value> | |||||
| struct getter_builder< | |||||
| list<T_value (T_object::*)()>, | |||||
| void> | |||||
| : public getter_builder_member_func<T_object, T_value, T_value (T_object::*)()> | |||||
| { }; | |||||
| template<typename T_object, typename T_value> | |||||
| struct getter_builder< | |||||
| list<T_value (T_object::*)() const>, | |||||
| void> | |||||
| : public getter_builder_member_func<T_object, T_value, T_value (T_object::*)() const> | |||||
| { }; | |||||
| /* getter_builder - lambda/static */ | |||||
| template<typename T_lambda> | |||||
| struct getter_builder< | |||||
| list<T_lambda>, | |||||
| enable_if_t< | |||||
| is_valid_v<lambda_traits<decay_t<T_lambda>>> | |||||
| && lambda_traits<decay_t<T_lambda>>::argument_count_v == 1 | |||||
| && !is_void_v<typename lambda_traits<decay_t<T_lambda>>::return_type>>> | |||||
| { | |||||
| struct getter_lambda | |||||
| : public tag_getter | |||||
| { | |||||
| using lambda_type = T_lambda; | |||||
| using lambda_traits_type = lambda_traits<lambda_type>; | |||||
| using object_type = typename lambda_traits_type::template argument_t<0>; | |||||
| using value_type = typename lambda_traits_type::return_type; | |||||
| lambda_type lambda; | |||||
| constexpr getter_lambda(lambda_type&& p_lambda) | |||||
| : lambda(std::forward<lambda_type>(p_lambda)) | |||||
| { } | |||||
| constexpr getter_lambda(getter_lambda&&) = default; | |||||
| constexpr getter_lambda(const getter_lambda&) = default; | |||||
| constexpr getter_lambda& operator = (getter_lambda&&) = default; | |||||
| constexpr getter_lambda& operator = (const getter_lambda&) = default; | |||||
| template<typename X_object> | |||||
| constexpr decltype(auto) operator()(X_object&& obj) const | |||||
| { return lambda(std::forward<X_object>(obj)); } | |||||
| }; | |||||
| using lambda_type = T_lambda; | |||||
| static constexpr decltype(auto) apply(lambda_type&& lambda) | |||||
| { return getter_lambda(std::forward<lambda_type>(lambda)); } | |||||
| }; | |||||
| } | |||||
| /* is_getter */ | |||||
| template<typename T> | |||||
| struct is_getter | |||||
| : public is_base_of<__impl::tag_getter, T> | |||||
| { }; | |||||
| } | |||||
| @@ -0,0 +1,41 @@ | |||||
| #pragma once | |||||
| #include "generic_predicate.h" | |||||
| namespace cppmp | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* tag_setter */ | |||||
| struct tag_setter; | |||||
| /* setter_builder */ | |||||
| template<typename X, typename = void> | |||||
| struct setter_builder; | |||||
| } | |||||
| /** | |||||
| * @brief Evaluates to true_t if the passed type is an setter, to false_t otherwise. | |||||
| */ | |||||
| template<typename T> | |||||
| struct is_setter; | |||||
| /** | |||||
| * @brief Is true if the passed type is an setter, false otherwise. | |||||
| */ | |||||
| template<typename T> | |||||
| constexpr decltype(auto) is_setter_v = is_setter<T>::value; | |||||
| /** | |||||
| * @brief Predicate to create new setter objects. | |||||
| */ | |||||
| constexpr decltype(auto) make_setter = generic_predicate<__impl::setter_builder> { }; | |||||
| } | |||||
| #include "setter.inl" | |||||
| @@ -0,0 +1,178 @@ | |||||
| #pragma once | |||||
| #include <cppmp/traits/lambda_traits.h> | |||||
| #include "setter.h" | |||||
| namespace cppmp | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* tag_setter */ | |||||
| struct tag_setter | |||||
| { }; | |||||
| /* setter_builder - default */ | |||||
| template<typename X, typename> | |||||
| struct setter_builder | |||||
| { | |||||
| template<typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&...) | |||||
| { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_setter(...)!"); } | |||||
| }; | |||||
| /* setter_builder - redirect existing setter */ | |||||
| template<typename T_setter> | |||||
| struct setter_builder< | |||||
| list<T_setter>, | |||||
| enable_if_t<is_setter_v<decay_t<T_setter>>>> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_setter&& setter) | |||||
| { return std::forward<T_setter>(setter); } | |||||
| }; | |||||
| /* setter_builder - member variable */ | |||||
| template<typename T_object, typename T_value> | |||||
| struct setter_builder< | |||||
| list<T_value T_object::*>, | |||||
| void> | |||||
| { | |||||
| struct setter_member_var | |||||
| : public tag_setter | |||||
| { | |||||
| using object_type = T_object; | |||||
| using value_type = T_value; | |||||
| using member_type = value_type object_type::*; | |||||
| member_type member; | |||||
| constexpr 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; | |||||
| constexpr setter_member_var& operator = (setter_member_var&&) = default; | |||||
| constexpr setter_member_var& operator = (const setter_member_var&) = default; | |||||
| template<typename X_object, typename X_value> | |||||
| constexpr void operator()(X_object&& obj, X_value&& value) const | |||||
| { std::forward<X_object>(obj).*member = value; } | |||||
| }; | |||||
| using object_type = T_object; | |||||
| using value_type = T_value; | |||||
| using member_type = value_type object_type::*; | |||||
| static constexpr decltype(auto) apply(member_type&& setter) | |||||
| { return setter_member_var(std::forward<member_type>(setter)); } | |||||
| }; | |||||
| /* setter_builder - member function */ | |||||
| template<typename T_object, typename T_value, typename T_member> | |||||
| struct setter_builder_member_func | |||||
| { | |||||
| struct setter_member_func | |||||
| : public tag_setter | |||||
| { | |||||
| using object_type = T_object; | |||||
| using value_type = T_value; | |||||
| using member_type = T_member; | |||||
| member_type member; | |||||
| constexpr 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; | |||||
| constexpr setter_member_func& operator = (setter_member_func&&) = default; | |||||
| constexpr setter_member_func& operator = (const setter_member_func&) = default; | |||||
| template<typename X_object, typename X_value> | |||||
| constexpr void operator()(X_object&& obj, X_value&& value) const | |||||
| { (std::forward<X_object>(obj).*member)(value); } | |||||
| }; | |||||
| using object_type = T_object; | |||||
| using value_type = T_value; | |||||
| using member_type = T_member; | |||||
| static constexpr decltype(auto) apply(member_type&& setter) | |||||
| { return setter_member_func(std::forward<member_type>(setter)); } | |||||
| }; | |||||
| template<typename T_object, typename T_value> | |||||
| struct setter_builder< | |||||
| list<void (T_object::*)(T_value)>, | |||||
| void> | |||||
| : public setter_builder_member_func<T_object, T_value, void (T_object::*)(T_value)> | |||||
| { }; | |||||
| template<typename T_object, typename T_value> | |||||
| struct setter_builder< | |||||
| list<void (T_object::*)(T_value) const>, | |||||
| void> | |||||
| : public setter_builder_member_func<T_object, T_value, void (T_object::*)(T_value) const> | |||||
| { }; | |||||
| /* setter_builder - lambda/static */ | |||||
| template<typename T_lambda> | |||||
| struct setter_builder< | |||||
| list<T_lambda>, | |||||
| enable_if_t< | |||||
| is_valid_v<lambda_traits<decay_t<T_lambda>>> | |||||
| && lambda_traits<decay_t<T_lambda>>::argument_count_v == 2>> | |||||
| { | |||||
| struct setter_lambda | |||||
| : public tag_setter | |||||
| { | |||||
| using lambda_type = T_lambda; | |||||
| using lambda_traits_type = lambda_traits<lambda_type>; | |||||
| using object_type = typename lambda_traits_type::template argument_t<0>; | |||||
| using value_type = typename lambda_traits_type::return_type; | |||||
| lambda_type lambda; | |||||
| constexpr setter_lambda(lambda_type&& p_lambda) | |||||
| : lambda(std::forward<lambda_type>(p_lambda)) | |||||
| { } | |||||
| constexpr setter_lambda(setter_lambda&&) = default; | |||||
| constexpr setter_lambda(const setter_lambda&) = default; | |||||
| constexpr setter_lambda& operator = (setter_lambda&&) = default; | |||||
| constexpr setter_lambda& operator = (const setter_lambda&) = default; | |||||
| template<typename X_object, typename X_value> | |||||
| constexpr void operator()(X_object&& obj, X_value&& value) const | |||||
| { lambda(std::forward<X_object>(obj), std::forward<X_value>(value)); } | |||||
| }; | |||||
| using lambda_type = T_lambda; | |||||
| static constexpr decltype(auto) apply(lambda_type&& lambda) | |||||
| { return setter_lambda(std::forward<lambda_type>(lambda)); } | |||||
| }; | |||||
| } | |||||
| /* is_setter */ | |||||
| template<typename T> | |||||
| struct is_setter | |||||
| : public is_base_of<__impl::tag_setter, T> | |||||
| { }; | |||||
| } | |||||
| @@ -0,0 +1,3 @@ | |||||
| #pragma once | |||||
| #include "traits/lambda_traits.h" | |||||
| @@ -0,0 +1,14 @@ | |||||
| #pragma once | |||||
| namespace cppmp | |||||
| { | |||||
| /** | |||||
| * @brief Contains type traits and other helpers for the passed lambda. | |||||
| */ | |||||
| template<typename T_lambda, typename = void> | |||||
| struct lambda_traits; | |||||
| } | |||||
| #include "lambda_traits.inl" | |||||
| @@ -0,0 +1,110 @@ | |||||
| #pragma once | |||||
| #include "lambda_traits.h" | |||||
| namespace cppmp | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* lambda_traits_impl */ | |||||
| template<bool B_is_mutable, typename T_object, typename T_return, typename... T_args> | |||||
| struct lambda_traits_impl | |||||
| { | |||||
| using object_type = T_object; | |||||
| using return_type = T_return; | |||||
| using arguments_type = std::tuple<T_args...>; | |||||
| using is_mutable = bool_t<B_is_mutable>; | |||||
| using is_static = is_same<object_type, void>; | |||||
| using argument_count = size_t<sizeof...(T_args)>; | |||||
| static constexpr decltype(auto) is_mutable_v = is_mutable::value; | |||||
| static constexpr decltype(auto) is_static_v = is_static::value; | |||||
| static constexpr decltype(auto) argument_count_v = argument_count::value; | |||||
| template<std::size_t I> | |||||
| struct argument | |||||
| : public std::tuple_element<I, arguments_type> | |||||
| { }; | |||||
| template<std::size_t I> | |||||
| using argument_t = typename argument<I>::type; | |||||
| }; | |||||
| } | |||||
| /* lambda_traits */ | |||||
| template<typename T_lambda> | |||||
| struct lambda_traits<T_lambda, enable_if_t<is_valid_v<decltype(&T_lambda::operator())>>> | |||||
| : public lambda_traits<decltype(&T_lambda::operator())> | |||||
| { }; | |||||
| template<typename T_return, typename... T_args> | |||||
| struct lambda_traits<T_return (*)(T_args...), void> | |||||
| : public __impl::lambda_traits_impl<false, void, T_return, T_args...> | |||||
| { }; | |||||
| template<typename T_object, typename T_return, typename... T_args> | |||||
| struct lambda_traits<T_return (T_object::*)(T_args...), void> | |||||
| : public __impl::lambda_traits_impl<true, T_object, T_return, T_args...> | |||||
| { }; | |||||
| template<typename T_object, typename T_return, typename... T_args> | |||||
| struct lambda_traits<T_return (T_object::*)(T_args...) const, void> | |||||
| : public __impl::lambda_traits_impl<false, T_object, T_return, T_args...> | |||||
| { }; | |||||
| } | |||||
| #pragma once | |||||
| #include <tuple> | |||||
| #include <type_traits> | |||||
| namespace stx | |||||
| { | |||||
| namespace lambda_detail | |||||
| { | |||||
| template<class Ret, class Cls, class IsMutable, class... Args> | |||||
| struct types | |||||
| { | |||||
| using is_mutable = IsMutable; | |||||
| enum { arity = sizeof...(Args) }; | |||||
| using return_type = Ret; | |||||
| template<size_t i> | |||||
| struct arg | |||||
| { | |||||
| typedef typename std::tuple_element<i, std::tuple<Args...>>::type type; | |||||
| }; | |||||
| }; | |||||
| } | |||||
| template<class Ld> | |||||
| struct lambda_type | |||||
| : lambda_type<decltype(&Ld::operator())> | |||||
| {}; | |||||
| template<class Ret, class Cls, class... Args> | |||||
| struct lambda_type<Ret(Cls::*)(Args...)> | |||||
| : lambda_detail::types<Ret,Cls,std::true_type,Args...> | |||||
| {}; | |||||
| template<class Ret, class Cls, class... Args> | |||||
| struct lambda_type<Ret(Cls::*)(Args...) const> | |||||
| : lambda_detail::types<Ret,Cls,std::false_type,Args...> | |||||
| {}; | |||||
| }; | |||||
| @@ -22,7 +22,7 @@ Add_Executable ( cppmp-test | |||||
| ${CPPMP_TEST_SOURCE_FILES} ) | ${CPPMP_TEST_SOURCE_FILES} ) | ||||
| Target_Link_Libraries ( cppmp-test | Target_Link_Libraries ( cppmp-test | ||||
| PUBLIC | PUBLIC | ||||
| cppmp-objects | |||||
| cppmp | |||||
| GTest::Main ) | GTest::Main ) | ||||
| # pedantic | # pedantic | ||||
| @@ -1,11 +0,0 @@ | |||||
| #include <gtest/gtest.h> | |||||
| #include <cppmp.h> | |||||
| using namespace ::testing; | |||||
| using namespace ::cppmp; | |||||
| TEST(cppmp, getHelloWorld) | |||||
| { | |||||
| EXPECT_EQ(Dummy::getHelloWorld(), "Hello World!"); | |||||
| } | |||||
| @@ -0,0 +1,67 @@ | |||||
| #include <gtest/gtest.h> | |||||
| #include <cppmp.h> | |||||
| using namespace ::testing; | |||||
| using namespace ::cppmp; | |||||
| struct test_obj | |||||
| { | |||||
| mutable int value; | |||||
| int get() | |||||
| { return value; } | |||||
| int cget() const | |||||
| { return value; } | |||||
| static int sget(test_obj& o) | |||||
| { return o.value; } | |||||
| }; | |||||
| TEST(cppmp_getter_tests, member_var) | |||||
| { | |||||
| test_obj o { 1 }; | |||||
| auto g = make_getter(&test_obj::value); | |||||
| EXPECT_EQ(1, g(o)); | |||||
| } | |||||
| TEST(cppmp_getter_tests, member_func) | |||||
| { | |||||
| test_obj o { 1 }; | |||||
| auto g = make_getter(&test_obj::get); | |||||
| EXPECT_EQ(1, g(o)); | |||||
| } | |||||
| TEST(cppmp_getter_tests, const_member_func) | |||||
| { | |||||
| test_obj o { 1 }; | |||||
| auto g = make_getter(&test_obj::cget); | |||||
| EXPECT_EQ(1, g(o)); | |||||
| } | |||||
| TEST(cppmp_getter_tests, static_func) | |||||
| { | |||||
| test_obj o { 1 }; | |||||
| auto g = make_getter(&test_obj::sget); | |||||
| EXPECT_EQ(1, g(o)); | |||||
| } | |||||
| TEST(cppmp_getter_tests, lambda) | |||||
| { | |||||
| test_obj o { 1 }; | |||||
| auto g = make_getter([](test_obj& o){ | |||||
| return o.value; | |||||
| }); | |||||
| EXPECT_EQ(1, g(o)); | |||||
| } | |||||
| @@ -0,0 +1,72 @@ | |||||
| #include <gtest/gtest.h> | |||||
| #include <cppmp.h> | |||||
| using namespace ::testing; | |||||
| using namespace ::cppmp; | |||||
| struct test_obj | |||||
| { | |||||
| mutable int value; | |||||
| void set(int v) | |||||
| { value = v; } | |||||
| void cset(int v) const | |||||
| { value = v; } | |||||
| static void sset(test_obj& o, int v) | |||||
| { o.value = v; } | |||||
| }; | |||||
| TEST(cppmp_setter_tests, member_var) | |||||
| { | |||||
| test_obj o { 0 }; | |||||
| auto s = make_setter(&test_obj::value); | |||||
| s(o, 1); | |||||
| EXPECT_EQ(1, o.value); | |||||
| } | |||||
| TEST(cppmp_setter_tests, member_func) | |||||
| { | |||||
| test_obj o { 1 }; | |||||
| auto s = make_setter(&test_obj::set); | |||||
| s(o, 1); | |||||
| EXPECT_EQ(1, o.value); | |||||
| } | |||||
| TEST(cppmp_setter_tests, const_member_func) | |||||
| { | |||||
| test_obj o { 1 }; | |||||
| auto s = make_setter(&test_obj::cset); | |||||
| s(o, 1); | |||||
| EXPECT_EQ(1, o.value); | |||||
| } | |||||
| TEST(cppmp_setter_tests, static_func) | |||||
| { | |||||
| test_obj o { 1 }; | |||||
| auto s = make_setter(&test_obj::sset); | |||||
| s(o, 1); | |||||
| EXPECT_EQ(1, o.value); | |||||
| } | |||||
| TEST(cppmp_setter_tests, lambda) | |||||
| { | |||||
| test_obj o { 1 }; | |||||
| auto s = make_setter([](test_obj& o, int v){ | |||||
| o.value = v; | |||||
| }); | |||||
| s(o, 1); | |||||
| EXPECT_EQ(1, o.value); | |||||
| } | |||||
| @@ -0,0 +1,3 @@ | |||||
| #include <gtest/gtest.h> | |||||
| #include <cppmp.h> | |||||
| @@ -0,0 +1,55 @@ | |||||
| #include <gtest/gtest.h> | |||||
| #include <cppmp.h> | |||||
| using namespace ::testing; | |||||
| using namespace ::cppmp; | |||||
| struct test_obj | |||||
| { | |||||
| int test(int); | |||||
| double ctest(float, std::string) const; | |||||
| static std::string sget(); | |||||
| }; | |||||
| constexpr decltype(auto) cpp_traits_lambda = [](std::string, int)->bool { return true; }; | |||||
| using type0 = ::cppmp::lambda_traits<decltype(&test_obj::test)>; | |||||
| using type1 = ::cppmp::lambda_traits<decltype(&test_obj::ctest)>; | |||||
| using type2 = ::cppmp::lambda_traits<decltype(&test_obj::sget)>; | |||||
| using type3 = ::cppmp::lambda_traits<std::string(*)(bool)>; | |||||
| using type4 = ::cppmp::lambda_traits<decltype(cpp_traits_lambda)>; | |||||
| 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_v<typename type1::object_type, 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_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_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_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); | |||||