// Copyright (c) 2019 GeometryFactory (France). All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Sebastien Loriot #ifndef CGAL_NAMED_FUNCTION_PARAMETERS_H #define CGAL_NAMED_FUNCTION_PARAMETERS_H #ifndef CGAL_NO_STATIC_ASSERTION_TESTS #include #endif #include #include #include #include #include #define CGAL_NP_TEMPLATE_PARAMETERS NP_T=bool, typename NP_Tag=CGAL::internal_np::all_default_t, typename NP_Base=CGAL::internal_np::No_property #define CGAL_NP_TEMPLATE_PARAMETERS_NO_DEFAULT NP_T, typename NP_Tag, typename NP_Base #define CGAL_NP_TEMPLATE_PARAMETERS_NO_DEFAULT_1 NP_T1, typename NP_Tag1, typename NP_Base1 #define CGAL_NP_TEMPLATE_PARAMETERS_NO_DEFAULT_2 NP_T2, typename NP_Tag2, typename NP_Base2 #define CGAL_NP_CLASS CGAL::Named_function_parameters #define CGAL_NP_TEMPLATE_PARAMETERS_1 NP_T1=bool, typename NP_Tag1=CGAL::internal_np::all_default_t, typename NP_Base1=CGAL::internal_np::No_property #define CGAL_NP_CLASS_1 CGAL::Named_function_parameters #define CGAL_NP_TEMPLATE_PARAMETERS_2 NP_T2=bool, typename NP_Tag2=CGAL::internal_np::all_default_t, typename NP_Base2=CGAL::internal_np::No_property #define CGAL_NP_CLASS_2 CGAL::Named_function_parameters #define CGAL_NP_TEMPLATE_PARAMETERS_VARIADIC NP_T, typename ... NP_Tag, typename ... NP_Base namespace CGAL { namespace internal_np{ struct No_property {}; struct Param_not_found {}; enum all_default_t { all_default }; // define enum types and values for new named parameters #define CGAL_add_named_parameter(X, Y, Z) \ enum X { Y }; #define CGAL_add_named_parameter_with_compatibility(X, Y, Z) \ enum X { Y }; #define CGAL_add_named_parameter_with_compatibility_cref_only(X, Y, Z) \ enum X { Y }; #define CGAL_add_named_parameter_with_compatibility_ref_only(X, Y, Z) \ enum X { Y }; #define CGAL_add_extra_named_parameter_with_compatibility(X, Y, Z) #include #undef CGAL_add_named_parameter #undef CGAL_add_named_parameter_with_compatibility #undef CGAL_add_named_parameter_with_compatibility_cref_only #undef CGAL_add_named_parameter_with_compatibility_ref_only #undef CGAL_add_extra_named_parameter_with_compatibility template struct Named_params_impl : Base { typename std::conditional::value, T, std::reference_wrapper >::type v; // copy of the parameter if copyable Named_params_impl(const T& v, const Base& b) : Base(b) , v(v) {} }; // partial specialization for base class of the recursive nesting template struct Named_params_impl { typename std::conditional::value, T, std::reference_wrapper >::type v; // copy of the parameter if copyable Named_params_impl(const T& v) : v(v) {} }; // Helper class to get the type of a named parameter pack given a query tag template struct Get_param; template< typename T, typename Tag, typename Query_tag> struct Get_param< Named_params_impl, Query_tag > { typedef Param_not_found type; typedef Param_not_found reference; }; template< typename T, typename Tag, typename Base> struct Get_param< Named_params_impl, Tag > { typedef typename std::conditional::value, T, std::reference_wrapper >::type type; typedef typename std::conditional::value, T, const T&>::type reference; }; template< typename T, typename Tag> struct Get_param< Named_params_impl, Tag > { typedef typename std::conditional::value, T, std::reference_wrapper >::type type; typedef typename std::conditional::value, T, const T&>::type reference; }; template< typename T, typename Tag, typename Base> struct Get_param< Named_params_impl, Tag, Base>, Tag > { typedef std::reference_wrapper type; typedef T& reference; }; template< typename T, typename Tag> struct Get_param< Named_params_impl, Tag, No_property>, Tag > { typedef std::reference_wrapper type; typedef T& reference; }; template< typename T, typename Tag, typename Base, typename Query_tag> struct Get_param< Named_params_impl, Query_tag> { typedef typename Get_param::type type; typedef typename Get_param::reference reference; }; // helper to choose the default template struct Lookup_named_param_def { typedef typename internal_np::Get_param::type NP_type; typedef typename internal_np::Get_param::reference NP_reference; typedef std::conditional_t< std::is_same_v, D, NP_type> type; typedef std::conditional_t< std::is_same_v, D&, NP_reference> reference; }; // helper function to extract the value from a named parameter pack given a query tag template typename std::conditional::value, T, std::reference_wrapper >::type get_parameter_impl(const Named_params_impl& np, Tag) { return np.v; } template< typename T, typename Tag, typename Query_tag> Param_not_found get_parameter_impl(const Named_params_impl&, Query_tag) { return Param_not_found(); } template< typename T, typename Tag> typename std::conditional::value, T, std::reference_wrapper >::type get_parameter_impl(const Named_params_impl& np, Tag) { return np.v; } template typename Get_param, Query_tag>::type get_parameter_impl(const Named_params_impl& np, Query_tag tag) { #ifndef CGAL_NO_STATIC_ASSERTION_TEST static_assert(!std::is_same::value); #endif return get_parameter_impl(static_cast(np), tag); } // helper for getting references template const T& get_reference(const T& t) { return t; } template T& get_reference(const std::reference_wrapper& r) { return r.get(); } // helper function to extract the reference from a named parameter pack given a query tag template typename std::conditional::value, T, const T& >::type get_parameter_reference_impl(const Named_params_impl& np, Tag) { return get_reference(np.v); } template< typename T, typename Tag, typename Query_tag> Param_not_found get_parameter_reference_impl(const Named_params_impl&, Query_tag) { return Param_not_found(); } template< typename T, typename Tag> typename std::conditional::value, T, const T& >::type get_parameter_reference_impl(const Named_params_impl& np, Tag) { return get_reference(np.v); } template T& get_parameter_reference_impl(const Named_params_impl, Tag, Base>& np, Tag) { return np.v.get(); } template< typename T, typename Tag> T& get_parameter_reference_impl(const Named_params_impl, Tag, No_property>& np, Tag) { return np.v.get(); } template typename Get_param, Query_tag>::reference get_parameter_reference_impl(const Named_params_impl& np, Query_tag tag) { static_assert(!std::is_same::value); return get_parameter_reference_impl(static_cast(np), tag); } } // end of internal_np namespace template struct Named_function_parameters; namespace parameters{ typedef Named_function_parameters Default_named_parameters; Default_named_parameters inline default_values(); // function to extract a parameter template typename internal_np::Get_param, Query_tag>::type get_parameter(const Named_function_parameters& np, Query_tag tag) { return internal_np::get_parameter_impl(static_cast&>(np), tag); } template typename internal_np::Get_param, Query_tag>::reference get_parameter_reference(const Named_function_parameters& np, Query_tag tag) { return internal_np::get_parameter_reference_impl( static_cast&>(np), tag); } // Two parameters, non-trivial default value template D& choose_parameter(const internal_np::Param_not_found&, D& d) { return d; } template const D& choose_parameter(const internal_np::Param_not_found&, const D& d) { return d; } template D choose_parameter(const internal_np::Param_not_found&, D&& d) { return std::forward(d); } template T& choose_parameter(T& t, D&) { return t; } template const T& choose_parameter(const T& t, const D&) { return t; } // single parameter so that we can avoid a default construction template D choose_parameter(const internal_np::Param_not_found&) { return D(); } template const T& choose_parameter(const T& t) { return t; } } // parameters namespace namespace internal_np { template auto combine_named_parameters(const Named_function_parameters& np, const NPS& ... nps) { return np.combine(nps ...); } } // end of internal_np namespace template struct Named_function_parameters : internal_np::Named_params_impl { typedef internal_np::Named_params_impl base; typedef Named_function_parameters self; Named_function_parameters() : base(T()) {} Named_function_parameters(const T& v) : base(v) {} Named_function_parameters(const T& v, const Base& b) : base(v, b) {} // create the functions for new named parameters and the one imported boost // used to concatenate several parameters #define CGAL_add_named_parameter(X, Y, Z) \ template \ Named_function_parameters \ Z(const K& k) const \ { \ typedef Named_function_parameters Params;\ return Params(k, *this); \ } #define CGAL_add_named_parameter_with_compatibility(X, Y, Z) \ template \ Named_function_parameters \ Z(const K& k) const \ { \ typedef Named_function_parameters Params;\ return Params(k, *this); \ } #define CGAL_add_named_parameter_with_compatibility_cref_only(X, Y, Z) \ template \ Named_function_parameters, \ internal_np::X, self> \ Z(const K& k) const \ { \ typedef Named_function_parameters,\ internal_np::X, self> Params; \ return Params(std::cref(k), *this); \ } #define CGAL_add_named_parameter_with_compatibility_ref_only(X, Y, Z) \ template \ Named_function_parameters, \ internal_np::X, self> \ Z(K& k) const \ { \ typedef Named_function_parameters, \ internal_np::X, self> Params; \ return Params(std::ref(k), *this); \ } #define CGAL_add_extra_named_parameter_with_compatibility(X, Y, Z) \ template \ Named_function_parameters \ Z(const K& k) const \ { \ typedef Named_function_parameters Params;\ return Params(k, *this); \ } #include #undef CGAL_add_named_parameter #undef CGAL_add_named_parameter_with_compatibility #undef CGAL_add_named_parameter_with_compatibility_cref_only #undef CGAL_add_named_parameter_with_compatibility_ref_only #undef CGAL_add_extra_named_parameter_with_compatibility // inject mesh specific named parameter functions #define CGAL_NP_BASE self #define CGAL_NP_BUILD(P, V) P(V, *this) #include #undef CGAL_NP_BASE #undef CGAL_NP_BUILD template Named_function_parameters combine(const Named_function_parameters& np) const { return Named_function_parameters(np.v,*this); } template auto combine(const Named_function_parameters& np, const NPS& ... nps) const { return Named_function_parameters(np.v,*this).combine(nps...); } // typedef for SFINAE typedef int CGAL_Named_function_parameters_class; }; namespace parameters { Default_named_parameters inline default_values() { return Default_named_parameters(); } #ifndef CGAL_NO_DEPRECATED_CODE Default_named_parameters inline all_default() { return Default_named_parameters(); } #endif template struct Boost_parameter_compatibility_wrapper { template Named_function_parameters operator()(const K& p) const { typedef Named_function_parameters Params; return Params(p); } template Named_function_parameters operator=(const K& p) const { typedef Named_function_parameters Params; return Params(p); } }; template struct Boost_parameter_compatibility_wrapper { template Named_function_parameters, Tag> operator()(const K& p) const { typedef Named_function_parameters, Tag> Params; return Params(std::cref(p)); } template Named_function_parameters, Tag> operator=(const K& p) const { typedef Named_function_parameters, Tag> Params; return Params(std::cref(p)); } }; template struct Boost_parameter_compatibility_wrapper { template Named_function_parameters, Tag> operator()(K& p) const { typedef Named_function_parameters, Tag> Params; return Params(std::ref(p)); } template Named_function_parameters, Tag> operator=(std::reference_wrapper p) const { typedef Named_function_parameters, Tag> Params; return Params(std::ref(p)); } }; // define free functions and Boost_parameter_compatibility_wrapper for named parameters #define CGAL_add_named_parameter(X, Y, Z) \ template \ Named_function_parameters \ Z(const K& p) \ { \ typedef Named_function_parameters Params;\ return Params(p); \ } #define CGAL_add_named_parameter_with_compatibility(X, Y, Z) \ inline const Boost_parameter_compatibility_wrapper Z; #define CGAL_add_named_parameter_with_compatibility_cref_only(X, Y, Z) \ inline const Boost_parameter_compatibility_wrapper Z; #define CGAL_add_named_parameter_with_compatibility_ref_only(X, Y, Z) \ inline const Boost_parameter_compatibility_wrapper Z; #define CGAL_add_extra_named_parameter_with_compatibility(X, Y, Z) \ inline const Boost_parameter_compatibility_wrapper Z; #include #undef CGAL_add_named_parameter #undef CGAL_add_extra_named_parameter_with_compatibility #undef CGAL_add_named_parameter_with_compatibility #undef CGAL_add_named_parameter_with_compatibility_cref_only #undef CGAL_add_named_parameter_with_compatibility_ref_only // Version with three parameters for dynamic property maps template D choose_parameter(const internal_np::Param_not_found&, Dynamic_tag tag, PolygonMesh& pm) { return get(tag, pm); } template const T& choose_parameter(const T& t, Dynamic_tag, PolygonMesh&) { return t; } template struct is_default_parameter { typedef typename internal_np::Lookup_named_param_def::type NP_type; static const bool value = std::is_same::value; typedef CGAL::Boolean_tag type; }; } // end of parameters namespace #ifndef CGAL_NO_DEPRECATED_CODE namespace Polygon_mesh_processing { namespace parameters = CGAL::parameters; } #endif } //namespace CGAL #ifndef CGAL_NO_STATIC_ASSERTION_TESTS // code added to avoid silent runtime issues in non-updated code namespace boost { template void get_param(CGAL::Named_function_parameters, Tag2) { static_assert(B && "You must use CGAL::parameters::get_parameter instead of boost::get_param"); } } #endif // For disambiguation using SFINAE BOOST_MPL_HAS_XXX_TRAIT_DEF(CGAL_Named_function_parameters_class) template inline constexpr bool is_named_function_parameter = has_CGAL_Named_function_parameters_class::value; #endif // CGAL_BOOST_FUNCTION_PARAMS_HPP