[英]Checking if variadic template parameters are unique using fold expressions
給定一個可變參數模板參數包,我想檢查使用inline constexpr bool
和fold表達式給出的所有類型是否唯一。 我喜歡這樣的東西:
template<class... T>
inline static constexpr bool is_unique = (... && (!is_one_of<T, ...>));
其中is_one_of
是一個正常工作的類似bool。 但是無論我將什么放入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>);
(感謝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...
時間(只有一次) 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> );
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.