Creating variational adoption of just a reference or pointer

I can create a variation template that only accepts pointers:

template<typename ... Types> void F(Types *... args); 

Or a variation template that accepts only links:

 template<typename ... Types> void F(Types &... args); 

How to create a template that accepts either a non-constant link or a pointer?
For instance.

 int a, b, c; F(a, &b); // => F<int &, int *> F(a, 3); // Error, 3 not pointer and cannot bind to non const-reference 

Note. The reference version may look fine, because it can bind to pointer links, but it is not, because it will not be bound to int * const

+5
source share
2 answers

We can write a flag to check if the type is a pointer or a non-constant reference:

 template <typename T> using is_pointer_or_ref = std::integral_constant<bool, std::is_pointer<T>::value || (std::is_lvalue_reference<T>::value && !std::is_const<typename std::remove_reference<T>::type>::value)>; 

Then we can write a tag to test this for a parameter package using Jonathan and_ :

 template<typename... Conds> struct and_ : std::true_type { }; template<typename Cond, typename... Conds> struct and_<Cond, Conds...> : std::conditional<Cond::value, and_<Conds...>, std::false_type>::type { }; template <typename... Ts> using are_pointer_or_ref = and_<is_pointer_or_ref<Ts>...>; 

Now we can use std::enable_if to check the type:

 template<typename ... Types, typename std::enable_if<are_pointer_or_ref<Types...>::value>::type* = nullptr> void F(Types&&... args){} 

Note that forwarding reference is necessary to determine the category of argument values, so link checking works correctly.

Live demo

+6
source

You can simply check the requirements for each type in Args - for example. In this way:

 // Helper templates template <bool...> struct bool_pack {}; template <bool b, bool... rest> struct all_of : std::is_same<bool_pack<b, rest...>, bool_pack<rest..., b>> {}; template <typename... Args> auto F(Args&&... args) -> std::enable_if_t<all_of<std::is_lvalue_reference<Args>{} or std::is_pointer<std::decay_t<Args>>{}...>{}> {} 

Assuming F used only with subtraction, only lvalues ​​and pointers are allowed. Demo with your example.

+1
source

All Articles