// 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 #define CGAL_BGL_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_BGL_NP_TEMPLATE_PARAMETERS_NO_DEFAULT NP_T, typename NP_Tag, typename NP_Base #define CGAL_BGL_NP_CLASS CGAL::Named_function_parameters #define CGAL_BGL_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_BGL_NP_CLASS_1 CGAL::Named_function_parameters #define CGAL_BGL_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_BGL_NP_CLASS_2 CGAL::Named_function_parameters 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 }; #include #undef CGAL_add_named_parameter 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 typename boost::mpl::if_< boost::is_same, D, NP_type>::type type; typedef typename boost::mpl::if_< boost::is_same, D&, NP_reference>::type 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 CGAL_static_assertion( (!boost::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) { CGAL_static_assertion( (!boost::is_same::value) ); return get_parameter_reference_impl(static_cast(np), tag); } } // 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); \ } #include #undef CGAL_add_named_parameter }; namespace parameters { typedef Named_function_parameters Default_named_parameters; #ifndef CGAL_NO_DEPRECATED_CODE Default_named_parameters inline all_default() { return Default_named_parameters(); } #endif Default_named_parameters inline default_values() { return Default_named_parameters(); } template Named_function_parameters inline no_parameters(Named_function_parameters) { typedef Named_function_parameters Params; return Params(); } // define free functions 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); \ } #include #undef CGAL_add_named_parameter // 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; } template constexpr bool is_default_parameter() { return std::is_same< typename internal_np::Get_param::type, internal_np::Param_not_found> ::value; } } // 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) { CGAL_static_assertion(B && "You must use CGAL::parameters::get_parameter instead of boost::get_param"); } } #endif #endif // CGAL_BOOST_FUNCTION_PARAMS_HPP