2013-06-10 8 views
24

バリデーションタイプのいずれかが第1のタイプと等しいかどうかを返すクラステンプレートを作成する方法を教えてください。それ以外の場合はfalsevariadic is_sameを作成するには?

is_same<T, A, B, C>::value; // true if T is one of A, B or C 

そしてTは、これらのタイプのいずれかと等しい場合、その静的valueメンバーはtrue次のようになります。私はこれを行うことができるようにしたいです。これどうやってするの?

+3

を明らかに(2人の人が同じ誤った解釈をした)私は自由にあなたの質問を少し言い換えました。 – syam

答えて

30

使用テンプレート再帰:

template<typename T, typename... Rest> 
struct is_any : std::false_type {}; 

template<typename T, typename First> 
struct is_any<T, First> : std::is_same<T, First> {}; 

template<typename T, typename First, typename... Rest> 
struct is_any<T, First, Rest...> 
    : std::integral_constant<bool, std::is_same<T, First>::value || is_any<T, Rest...>::value> 
{}; 

static_assert(is_any<int, char, double, int>::value, "error 1"); // OK 
static_assert(is_any<int, char, double, short>::value, "error 2"); // error 
+0

ありがとうございました。 :) –

7

このようなものです。まず、小さなメタプログラミングライブラリ、それは一般的にそれを行うには2行と同じように追加されますので:次に

template<template<typename,typename>class checker, typename... Ts> 
struct is_any_to_first : std::false_type {}; 

template<template<typename,typename>class checker, typename T0, typename T1, typename... Ts> 
struct is_any_to_first<checker, T0, T1, Ts...> : 
    std::integral_constant< bool, checker<T0, T1>::value || is_any_to_first<checker, T0, Ts...>::value> 
{}; 

is_any_same_to_firstの2行の実装:

template<typename... Ts> 
using is_any_same_to_first = is_any_to_first< std::is_same, Ts... >; 

万全を期すために、オリジナルのis_all月また、有用であることが分かる:is_all_same

template<template<typename,typename>class checker, typename... Ts> 
struct is_all : std::true_type {}; 

template<template<typename,typename>class checker, typename T0, typename T1, typename... Ts> 
struct is_all<checker, T0, T1, Ts...> : 
    std::integral_constant< bool, checker<T0, T1>::value && is_all<checker, T0, Ts...>::value> 
{}; 

template<typename... Ts> 
using is_all_same = is_all< std::is_same, Ts... >; 

Live exampleを。

is_any_same_to_firstをあまり明示しないと、問題が発生することに注意してください。私を含めてこの質問に答えようとした2/3人が、同じ3つのタイプの場合にis_same<A,B,C>が真であると仮定しました!

+0

ええと私はあなたが私よりも(is_anyの代わりに 'is_all_same')他の決定をしたのを見ます。真実を伝えて、私はそれについての明確化のためにOPに尋ねることをためらった。 – syam

+0

Um ...このコードは、* all *型が同じ場合にのみ機能します。私は 'T'が' 'A'、' B'、 'C'のいずれかであるか探しています。 –

2

リラックスしたC++ 14 constexprの機能を使用して、物事のこれらの種類は、コードにはるかに簡単であり、あなたが書くことができるので、おそらくずっと速く、同様にコンパイルする:

template <class T, class ... Candidates> 
constexpr bool is_all_same() { 
    bool pairs[] = {std::is_same_v<T,Candidates>...}; 
    for(bool p: pairs) if(!p) return false; 
    return true; 
} 

template <class T, class ... Candidates> 
constexpr bool is_any_same() { 
    bool pairs[] = {std::is_same_v<T,Candidates>...}; 
    for(bool p: pairs) if(p) return true; 
    return false; 
} 

これは、C++でconstexpr関数がforループを持つことができるという事実によって有効になります。

template <class T, class... Ts> 
struct is_any : std::disjunction<std::is_same<T, Ts>...> {}; 

とデュアル::ニースとC++ 17と簡潔な

10

template <class T, class... Ts> 
struct are_same : std::conjunction<std::is_same<T, Ts>...> {}; 

表現倍使用していますバリエーション:あなたの意図はなかったので

template <class T, class... Ts> 
struct is_any : std::bool_constant<(std::is_same_v<T, Ts> || ...)> {}; 

template <class T, class... Ts> 
struct are_same : std::bool_constant<(std::is_same_v<T, Ts> && ...)> {}; 
関連する問題