I can create a variadic template that accepts only pointers:
template<typename ... Types>
void F(Types *... args);
Or a variadic template that accepts only references:
template<typename ... Types>
void F(Types &... args);
How can I create a template that accepts either non-const reference or pointer?
E.g.
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 might seem ok because it can bind to pointer references but it is not since it will not bind to int * const
We can write a trait to check if a type is a pointer or a non-const 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 trait to check this over a parameter pack using Jonathan Wakely's 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 validate the type:
template<typename ... Types,
typename std::enable_if<are_pointer_or_ref<Types...>::value>::type* = nullptr>
void F(Types&&... args){}
Note that the forwarding reference is necessary to detect the value category of the argument so that the reference check works correctly.
Live Demo
You can simply check the requirements for each type in Args
- e.g. thusly:
// 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 that F
is used with deduction only, solely lvalues and pointers will be allowed. Demo with your example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With