使用折叠表达式检查可变参数模板参数是否唯一
Checking if variadic template parameters are unique using fold expressions
给定一个可变参数模板参数包,我想使用inline constexpr bool
和折叠表达式检查提供给它的所有类型的类型是否都是唯一的。我尝试这样的事情:
template<class... T>
inline static constexpr bool is_unique = (... && (!is_one_of<T, ...>));
其中is_one_of
是一个正常工作的类似布尔值。 但是无论我放入is_one_of什么,这行都不会编译。这甚至可以使用折叠表达式来完成吗,还是我需要为此目的使用常规结构?
您的方法实际上不起作用,因为需要使用类型T
调用is_one_of
并且所有其他类型不包括T
。无法在单个参数包上使用折叠表达式来表达这一点。我建议改用专业化:
template <typename...>
inline constexpr auto is_unique = std::true_type{};
template <typename T, typename... Rest>
inline constexpr auto is_unique<T, Rest...> = std::bool_constant<
(!std::is_same_v<T, Rest> && ...) && is_unique<Rest...>
>{};
用法:
static_assert(is_unique<>);
static_assert(is_unique<int>);
static_assert(is_unique<int, float, double>);
static_assert(!is_unique<int, float, double, int>);
wandbox.org 上的现场示例
(感谢 Barry 使用折叠表达式的简化。
--编辑 --
谷歌搜索我找到了一个有趣的解决方案,它给了我灵感来避免递归并避免很多警告
因此,您可以定义类型的包装器
template <typename>
struct wrapT
{ };
以及从类型包装器继承的类型和整数的包装器
template <typename T, std::size_t>
struct wrapTI : public wrapT<T>
{ };
接下来,您可以定义一个递归继承自的wrapTI
foo
类
template <typename T,
typename = std::make_index_sequence<std::tuple_size<T>::value>>
struct foo;
template <typename ... Ts, std::size_t ... Is>
struct foo<std::tuple<Ts...>, std::index_sequence<Is...>>
: public wrapTI<Ts, Is>...
{ };
现在is_unique
可以是这样的
template <typename ... Ts>
static constexpr bool isUnique
= ( ... && std::is_convertible<foo<std::tuple<Ts...>>, wrapT<Ts>>::value );
关键是,只有当foo<Ts...>
从wrapT<T>
继承一次(并且只有一次)时,foo<Ts...>
才能转换为wrapT<T>
,也就是说,如果T
在Ts...
中存在一次(并且只有一次)。
以下是完整的编译示例
#include <tuple>
#include <type_traits>
template <typename>
struct wrapT
{ };
template <typename T, std::size_t>
struct wrapTI : public wrapT<T>
{ };
template <typename T,
typename = std::make_index_sequence<std::tuple_size<T>::value>>
struct foo;
template <typename ... Ts, std::size_t ... Is>
struct foo<std::tuple<Ts...>, std::index_sequence<Is...>>
: public wrapTI<Ts, Is>...
{ };
template <typename ... Ts>
static constexpr bool isUnique
= ( ... && std::is_convertible<foo<std::tuple<Ts...>>, wrapT<Ts>>::value );
int main ()
{
static_assert( true == isUnique<int, long, long long> );
static_assert( false == isUnique<int, long, long long, int> );
}
相关文章:
- 在C++中,使用带有 std::optional 参数的函数<T>来表示可选参数是否有意义?
- 如何检查给定的参数是否为 cv::noArray()?
- 如果返回 -1,时间() 的参数是否被修改?
- C++中大多数/所有 setter 函数的参数是否应该写为常量引用?
- 检查两个模板参数是否相同
- 空函数的参数是否加载到缓存中?
- 使用 lambda 作为构造函数参数是否需要C++ 17?
- 了解'this'或其他参数是否为右值
- const-ref传递的模板化参数是否经过优化,以便在足够小时按值传递
- shared_ptr构造函数参数是否应按值传递
- 如何检查模板参数是否为给定值?
- 使用聚合初始化模拟默认函数参数是否存在任何陷阱?
- 在对象序列化期间添加额外参数是否有更好的方法?
- 通过 ssh 发送参数.是否有非阻塞输入函数?
- 如何检查运算符 != 模板参数是否存在 C++ 17?
- 常量引用函数参数:是否可以禁止临时对象?
- 如何检查模板参数是否为 std::variant?
- 是否可以确定函数的参数是否已签名或无符号,以实现可能性超载函数
- 移动 l 值参考参数是否是一种不好的做法?
- 显式指定通用 lambda 的 operator() 模板参数是否合法?