创建仅接受引用或指针的可变参数
Creating variadic accepting only reference or pointer
我可以创建一个只接受指针的可变模板:
template<typename ... Types>
void F(Types *... args);
或者只接受引用的可变参数模板:
template<typename ... Types>
void F(Types &... args);
如何创建接受非常量引用或指针的模板?
例如
int a, b, c;
F(a, &b); // => F<int &, int *>
F(a, 3); // Error, 3 not pointer and cannot bind to non const-reference
注意:引用版本可能看起来不错,因为它可以绑定到指针引用,但事实并非如此,因为它不会绑定到 int * const
您可以在 Args
中简单地检查每种类型的要求 - 例如因此:
// 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>>{}...>{}>
{}
假设 F
仅用于推导,则仅允许左值和指针。 Demo以你的例子。
我们可以写一个特征来检查一个类型是指针还是非常量引用:
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)>;
然后我们可以使用 :
编写特征来检查参数包
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>...>;
现在我们可以使用std::enable_if
来验证类型:
template<typename ... Types,
typename std::enable_if<are_pointer_or_ref<Types...>::value>::type* = nullptr>
void F(Types&&... args){}
请注意,转发引用对于检测参数的值类别是必需的,以便引用检查正常工作。
我可以创建一个只接受指针的可变模板:
template<typename ... Types>
void F(Types *... args);
或者只接受引用的可变参数模板:
template<typename ... Types>
void F(Types &... args);
如何创建接受非常量引用或指针的模板?
例如
int a, b, c;
F(a, &b); // => F<int &, int *>
F(a, 3); // Error, 3 not pointer and cannot bind to non const-reference
注意:引用版本可能看起来不错,因为它可以绑定到指针引用,但事实并非如此,因为它不会绑定到 int * const
您可以在 Args
中简单地检查每种类型的要求 - 例如因此:
// 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>>{}...>{}>
{}
假设 F
仅用于推导,则仅允许左值和指针。 Demo以你的例子。
我们可以写一个特征来检查一个类型是指针还是非常量引用:
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)>;
然后我们可以使用
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>...>;
现在我们可以使用std::enable_if
来验证类型:
template<typename ... Types,
typename std::enable_if<are_pointer_or_ref<Types...>::value>::type* = nullptr>
void F(Types&&... args){}
请注意,转发引用对于检测参数的值类别是必需的,以便引用检查正常工作。