diff --git a/BGL/include/CGAL/boost/graph/Named_function_parameters.h b/BGL/include/CGAL/boost/graph/Named_function_parameters.h index c007da67960..b5bee02370d 100644 --- a/BGL/include/CGAL/boost/graph/Named_function_parameters.h +++ b/BGL/include/CGAL/boost/graph/Named_function_parameters.h @@ -66,6 +66,7 @@ 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> @@ -73,6 +74,8 @@ 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> @@ -80,6 +83,22 @@ 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; }; @@ -87,6 +106,7 @@ 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 @@ -94,11 +114,17 @@ 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 @@ -132,6 +158,68 @@ get_parameter_impl(const Named_params_impl& np, Query_tag tag) return get_parameter_impl(static_cast(np), tag); } + +// helper for getting references +template +T& get_reference(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(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(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(Named_params_impl& np, Tag) +{ + return get_reference(np.v); +}; + +template +T& +get_parameter_reference_impl(Named_params_impl, Tag, Base>& np, Tag) +{ + return np.v.get(); +} + +template< typename T, typename Tag> +T& +get_parameter_reference_impl(Named_params_impl, Tag, No_property>& np, Tag) +{ + return np.v.get(); +}; + + +template +typename Get_param, Query_tag>::type +get_parameter_reference_impl(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 @@ -204,15 +292,24 @@ 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&>(const_cast&>(np)), + tag); +} + // Two parameters, non-trivial default value template -D choose_parameter(const internal_np::Param_not_found&, const D& d) +D& choose_parameter(const internal_np::Param_not_found&, D& d) { return d; } template -const T& choose_parameter(const T& t, const D&) +T& choose_parameter(T& t, D&) { return t; } diff --git a/BGL/test/BGL/test_cgal_bgl_named_params.cpp b/BGL/test/BGL/test_cgal_bgl_named_params.cpp index 349f7b02302..2abe9a28665 100644 --- a/BGL/test/BGL/test_cgal_bgl_named_params.cpp +++ b/BGL/test/BGL/test_cgal_bgl_named_params.cpp @@ -4,6 +4,9 @@ #include +namespace inp = CGAL::internal_np; +namespace params = CGAL::parameters; + template struct A { @@ -28,29 +31,58 @@ void check_same_type(T) template void test_values_and_types(const NamedParameters& np) { - using CGAL::parameters::get_parameter; + using params::get_parameter; // test values - assert(get_parameter(np, CGAL::internal_np::vertex_index).v == 0); - assert(get_parameter(np, CGAL::internal_np::visitor).v == 1); + assert(get_parameter(np, inp::vertex_index).v == 0); + assert(get_parameter(np, inp::visitor).v == 1); // test types - check_same_type<0>(get_parameter(np, CGAL::internal_np::vertex_index)); - check_same_type<1>(get_parameter(np, CGAL::internal_np::visitor)); + check_same_type<0>(get_parameter(np, inp::vertex_index)); + check_same_type<1>(get_parameter(np, inp::visitor)); } template void test_no_copyable(const NamedParameters&) { - typedef typename CGAL::internal_np::Get_param::type NP_type; + typedef typename inp::Get_param::type NP_type; static_assert( boost::is_same > ::value ); } +template +void test_references(const NamedParameters& np) +{ + typedef A<2> Default_type; + Default_type default_value(2); + + // std::reference_wrapper + typedef typename inp::Lookup_named_param_def::reference Visitor_reference_type; + static_assert(std::is_same::value); + Visitor_reference_type vis_ref = params::choose_parameter(params::get_parameter_reference(np, inp::visitor), default_value); + CGAL_USE(vis_ref); + + // non-copyable + typedef typename inp::Lookup_named_param_def::reference VPM_reference_type; + static_assert(std::is_same::value); + VPM_reference_type vpm_ref = params::choose_parameter(params::get_parameter_reference(np, inp::vertex_point), default_value); + CGAL_USE(vpm_ref); + + // passed by copy + typedef typename inp::Lookup_named_param_def::reference VIM_reference_type; + static_assert(std::is_same&, VIM_reference_type>::value); + VIM_reference_type vim_ref = params::choose_parameter(params::get_parameter_reference(np, inp::vertex_index), default_value); + CGAL_USE(vim_ref); +} + int main() { - test_values_and_types(CGAL::parameters::vertex_index_map(A<0>(0)).visitor(A<1>(1))); + test_values_and_types(params::vertex_index_map(A<0>(0)).visitor(A<1>(1))); B b; - test_no_copyable(CGAL::parameters::visitor(b)); + test_no_copyable(params::visitor(b)); + + test_references(params::visitor(std::ref(b)) + .vertex_point_map(b) + .vertex_index_map(A<0>(0))); return EXIT_SUCCESS; }