Implementation of concepts in C++17 - c++

I'd seen the Bjarne stroustrup's talk named "Concepts the future of generic programming" and I thought maybe I can write "Concepts" in C++17...
But I'm a C programmer I've start with C++ about 6 months ago... so I don't know why but I've got e trouble with this code. Somebody can help me?
I'd implemented the Addable's concept with a shortly tmp code...
The idea is that will be in C++20 will be something like this:
template<typename T>
concept Summable = requires(T x) { x + x; };
template<typename T> requires Summable<T>
T sum(T n1, T n2) {
return n1 + n2;
}
And this code is what actually have in C++17:
template <typename, typename, typename = void>
struct Addable : std::false_type {};
template <typename T, typename U>
struct Addable < T, U,
std::void_t<decltype(std::declval<T&>()+std::declval<U&>())> >
: std::true_type {};
The top's code compile and works, but when I whrite the following code doesn't compile...
template<typename Head, typename ... Tail>
auto sum(Head h, Tail ... args) {
static_assert(Addable<Head, Tail...>::value, "Requires addable objects");
return h+(args+...);
}

You might change you assertion to
template <typename Head, typename ... Tail>
auto sum(Head h, Tail ... args) {
static_assert((Addable<Head, Tail>::value || ...), "Requires addable objects");
return (h + ... + args);
}
as your traits only works for 2 types.
Notice that SFINAE looks more like concept than static_assert.

Your code does work as long as you only provide two arguments to sum.
The problem is that when you call something like sum(1, 2, 3), Addable<Head, Tail...> becomes Addable<int, int, int>, which doesn't match your Addable<T, U, void> partial specialization. If you call sum with more than three arguments then there's no Addable template that matches at all, since Addable only accepts three template parameters.
If you want to be able to deal with more than two arguments, you'll need a different approach. This is what I came up with. It uses a similar approach to what you used, just with an extra layer indirection to support more than two arguments:
template <typename T, typename U, typename = void>
struct Helper : std::false_type {};
template <typename T, typename U>
struct Helper<T, U, std::void_t<decltype(std::declval<T>() + std::declval<U>())>> : std::true_type {};
template <typename, typename...>
struct Addable : std::false_type {};
template <typename T, typename U, typename... V>
struct Addable<T, U, V...> : std::conditional_t<Addable<T, U>::value,
Addable<U, V...>,
std::false_type> {};
template <typename T, typename U>
struct Addable<T, U> : Helper<T, U> {};
template<typename Head, typename ... Tail>
auto sum(Head h, Tail ... args) {
static_assert(Addable<Head, Tail...>::value, "Requires addable objects");
return h+(args+...);
}
Live Demo

Related

implementing typelist replace operation using variadic templates

I'm trying to implement a ReplaceAll metafunction for variadic template version of typelists (inspired by Modern C++ Design) and so far I could achieve the desired outcome with the following code:
template <typename... Elements> struct Typelist {};
//
// helper metafunction to set "Head" of typelist
//
template <typename TList, typename T> struct PushFrontT;
template <typename... Elements, typename T>
struct PushFrontT<Typelist<Elements...>, T> {
using Result = Typelist<T, Elements...>;
};
//
// metafunction to replace all occurences of "T" with "U"
//
template <typename TList, typename T, typename U> struct ReplaceAll;
template <typename T, typename U>
struct ReplaceAll<Typelist<>, T, U> {
using Result = Typelist<>;
};
template <typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<T, Tail...>, T, U> {
using Result = typename PushFrontT<
typename ReplaceAll<Typelist<Tail...>, T, U>::Result, U
>::Result;
};
template <typename Head, typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<Head, Tail...>, T, U> {
using Result = typename PushFrontT<
typename ReplaceAll<Typelist<Tail...>, T, U>::Result, Head
>::Result;
};
Which returns a typelist in the form of Typelist<T1, T2, T3> (effectively replacing all occurrences of type T with the target type U).
Now the problem is that when I try to not use the helper metafunction PushFrontT, a nested typelist structure would be created in the form of Typelist<T1, Typelist<T2, Typelist<T3, Typelist<>>>> which is incorrect (despite replacing all instances of T with U).
The code for the incorrect version is as follows:
template <typename T, typename U>
struct ReplaceAll<Typelist<>, T, U> {
using Result = Typelist<>;
};
template <typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<T, Tail...>, T, U> {
using Result = Typelist<U,
typename ReplaceAll<Typelist<Tail...>, T, U>::Result
>;
};
template <typename Head, typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<Head, Tail...>, T, U> {
using Result = Typelist<Head,
typename ReplaceAll<Typelist<Tail...>, T, U>::Result
>;
};
Based on my limited knowledge of variadic templates, I think the additional Typelist is a side effect of a pack expansion but I'm not sure.
Here is a simple test program to check the aforementioned code:
#include <type_traits>
int main () {
using tlist = Typelist<int, char, int, double>;
static_assert(
std::is_same<
typename ReplaceAll<tlist, int, long>::Result,
Typelist<long, char, long, double>>::value,
"Incorrect typelist!"
);
return(0);
}
In short, my question is how should I get rid of the excessive nested Typelists without using an outside helper metafunction such as PushFrontT?
You might simplify your code and get rid of the recursion with
template <typename TList, typename T, typename U> struct ReplaceAll;
template <typename ... Ts, typename T, typename U>
struct ReplaceAll<Typelist<Ts...>, T, U>
{
using Result = Typelist<std::conditional_t<std::is_same_v<Ts, T>, U, Ts>...>;
};
Demo

Subset a Variadic template given a constexpr boolean selection function

Suppose we have a variadic templated class like
template<class...Ts>
class X{
template<size_t I>
constexpr bool shouldSelect();
std::tuple<TransformedTs...> mResults; // this is want I want eventually
};
where the implementation of shouldSelect is not provided, but what it does is that, given an index i referring to the ith element of the variadic Ts, tells you whether we should select it to the subset.
I want to do a transformation on Ts such that only classes Ts at indexes that results in shouldSelect returning true should be selected. Is there an easy way to do this?
For example, if shouldSelect returns true for I = 1,2,4, and Ts... = short, int, double, T1, T2, then I want to get a TransformedTs... that is made up of int, double, T2. Then I can use this TransformedTs... in the same class.
If you're able to use C++17, this is pretty easy to implement using a combination of if constexpr and expression folding.
Start with some helper types, one with parameters to track the arguments to X::shouldSelect<I>(), and the other with a type to test.
template <typename T, size_t I, typename...Ts>
struct Accumulator {
using Type = std::tuple<Ts...>;
};
template <typename T>
struct Next { };
Then an operator overload either adds the type to the accumulator, or not with if constexpr:
template <typename TAcc, size_t I, typename... Ts, typename TArg>
decltype(auto) operator +(Accumulator<TAcc, I, Ts...>, Next<TArg>) {
if constexpr (TAcc::template shouldSelect<I>()) {
return Accumulator<TAcc, I + 1, Ts..., TArg>{};
} else {
return Accumulator<TAcc, I + 1, Ts...>{};
}
}
Finally, you can put it all together with a fold expression and extract the type with decltype:
template <template <typename... Ts> class T, typename... Ts>
constexpr decltype(auto) FilterImpl(const T<Ts...>&) {
return (Accumulator<T<Ts...>, 0>{} + ... + Next<Ts>{});
}
template<typename T>
using FilterT = typename decltype(FilterImpl(std::declval<T>()))::Type;
Usage:
using Result = FilterT<X<int, double, bool, etc>>;
Demo: https://godbolt.org/z/9h89zG
If you don't have C++17 available to you, it's still possible. You can do the same sort of conditional type transfer using a recursive inheritance chain to iterate though each type in the parameter pack, and std::enable_if to do the conditional copy. Below is the same code, but working in C++11:
// Dummy type for copying parameter packs
template <typename... Ts>
struct Mule {};
/* Filter implementation */
template <typename T, typename Input, typename Output, size_t I, typename = void>
struct FilterImpl;
template <typename T, typename THead, typename... TTail, typename... OutputTs, size_t I>
struct FilterImpl<T, Mule<THead, TTail...>, Mule<OutputTs...>, I, typename std::enable_if<( T::template shouldSelect<I>() )>::type >
: FilterImpl<T, Mule<TTail...>, Mule<OutputTs..., THead>, (I + 1)>
{ };
template <typename T, typename THead, typename... TTail, typename... OutputTs, size_t I>
struct FilterImpl<T, Mule<THead, TTail...>, Mule<OutputTs...>, I, typename std::enable_if<( !T::template shouldSelect<I>() )>::type >
: FilterImpl<T, Mule<TTail...>, Mule<OutputTs...>, (I + 1)>
{ };
template <typename T, typename... OutputTs, size_t I>
struct FilterImpl<T, Mule<>, Mule<OutputTs...>, I>
{
using Type = std::tuple<OutputTs...>;
};
/* Helper types */
template <typename T>
struct Filter;
template <template <typename... Ts> class T, typename... Ts>
struct Filter<T<Ts...>> : FilterImpl<T<Ts...>, Mule<Ts...>, Mule<>, 0>
{ };
template <typename T>
using FilterT = typename Filter<T>::Type;
Demo: https://godbolt.org/z/esso4M

Expanding with pack of templates

Define template_pack as in the following example. Given
template <typename> struct A;
template <typename, typename, typename> struct B;
template <typename, typename> struct C;
then
template_pack<std::tuple<char, bool, double>, A, B, C>::type
is to be
std::tuple<A<char>, B<char, bool, double>, C<char, bool>>
i.e. always reading from left to right in the tuple, so as to get enough types to fit each template.
Here's my solution so far. But it only works for templates that take up to 3 types, and I don't see how I can generalize to templates of any number of types:
#include <type_traits>
#include <tuple>
template <template <typename...> class Template, typename... Ts> struct use_template;
template <template <typename> class Template, typename A, typename... Rest>
struct use_template<Template, A, Rest...> {
using type = Template<A>;
};
template <template <typename, typename> class Template, typename A, typename B, typename... Rest>
struct use_template<Template, A, B, Rest...> {
using type = Template<A,B>;
};
template <template <typename, typename, typename> class Template, typename A, typename B, typename C, typename... Rest>
struct use_template<Template, A, B, C, Rest...> {
using type = Template<A,B,C>;
};
template <typename Pack, template <typename...> class... Templates> struct template_pack;
template <template <typename...> class P, typename... Ts, template <typename...> class... Templates>
struct template_pack<P<Ts...>, Templates...> {
using type = P<typename use_template<Templates, Ts...>::type...>;
};
// Testing
template <typename> struct A;
template <typename, typename, typename> struct B;
template <typename, typename> struct C;
int main() {
static_assert (std::is_same<
template_pack<std::tuple<char, bool, double>, A, B, C>::type,
std::tuple<A<char>, B<char, bool, double>, C<char, bool>>
>::value, "");
}
How to generalize the above? Is it even possible?
This is "find shortest prefix".
Utilities:
// pack that is easy to append to
template<class... Ts>
struct pack{
template<class... T1s>
using append = pack<Ts..., T1s...>;
};
template<class...> using void_t = void;
The meat:
// find the shortest proper prefix Ts... of [T, Rest...]
// such that A<Ts...> is well-formed, and return it.
template<template<class...> class A, // template we are going to look at
class AlwaysVoid, // for void_t
class Current, // pack containing the types we are testing next
class T, // next type to add to pack if test fails
class... Rest> // remaining types
struct find_viable
: find_viable<A, AlwaysVoid, typename Current::template append<T>, Rest...> {};
// picked if A<Ts...> is well-formed
template<template<class...> class A, class... Ts, class T, class...Rest>
struct find_viable<A, void_t<A<Ts...>>, pack<Ts...>, T, Rest...> {
using type = A<Ts...>;
};
// Finds the shortest prefix of Ts... such that A<prefix...> is well formed.
// the extra void at the end is slightly hackish - find_viable only checks
// proper prefixes, so we add an extra dummy type at the end.
template<template<class...> class A, class... Ts>
using find_viable_t = typename find_viable<A, void, pack<>, Ts..., void>::type;
Then use it:
template <typename Pack, template <typename...> class... Templates> struct template_pack;
template <template <typename...> class P, typename... Ts,
template <typename...> class... Templates>
struct template_pack<P<Ts...>, Templates...> {
using type = P<find_viable_t<Templates, Ts...>...>;
};
I won't write it all, but I'll do a walkthrough.
template<template<class...>class Z>
struct z_template{
template<class...Ts>using result=Z<Ts...>;
};
this lets you manipulate templates like types.
template<template<class...>class Z, class...Ts>
using can_apply = /* ... */;
this asks the question "is Z<Ts...> valid? If so, return true_type".
template<class...>struct types{using type=types;};
this is a light-weight template pack.
template<template<class...>class Z, class types>
using apply = /* ... */;
this takes a template Z, and a types<Ts...>, and returns Z<Ts...>.
template<class Z, class types>
using z_apply = apply<typename Z::template result, types>;
this does it with a z_template argument instead of a template one.
Working on types as often as possible makes many kinds of metaprogramming easier.
Next we write
template<class types>using pop_front = // ...
template<class types>using reverse = // ...
template<class types>using pop_back = reverse<pop_front<reverse<types>>>;
which remove elements from the front and back of types.
template<class Result>
struct z_constant {
template<class...Ts>using result=Result;
};
This finds the longest prefix of types that can be passed to Z::template result<???> validly. Some work to avoid passing too-short sequences is done, in case they fail "late":
template<class Z, class types>
struct z_find_longest_prefix :
std::conditional_t<
can_apply< z_apply, Z, types >{},
z_constant<types>,
z_template<longest_prefix>
>::template result<Z, pop_back<types>>
{};
template<class Z, class types>
using z_find_longest_prefix_t = typename z_find_longest_prefix<Z,types>::type;
struct empty_t {};
template<class Z>
struct z_find_longest_prefix<Z,types<>>:
std::conditional_t<
can_apply< Z::template result >,
types<>,
empty_t
>
{};
find_longest_prefix will fail to compile if there is no valid prefix.
template<class Z, class types>
using z_apply_longest_prefix_t =
z_apply< Z, z_find_longest_prefix_t<Z, types> >;
template<class src, template<class...>class... Zs>
struct use_template;
template<class src, template<class...>class... Zs>
using use_template_t = typename use_template<src, Zs...>::type;
template<template<class...>class Z0, class...Ts, template<class...>class... Zs>
struct use_template< Z0<Ts...>, Zs... > {
using type=Z0<
z_apply_longest_prefix_t<
z_template<Zs>, types<Ts...>
>...
>;
};
and up to typos and similar problems, done.
Can be cleaned up lots. Probably the entire z_ subsystem isn't needed. I just tend to run towards it whenever doing serious metaprogramming, because suddenly any metafunction I write that applies to types now can be used on templates.
reverse takes a bit of work to do efficiently.
can_apply is available in many of my posts.
pop_front is trivial.
apply should be easy.
This looked fun so I tried my hand at it; I'm not claiming this is in any way better than the existing answers, but maybe some people will find it clearer:
namespace detail {
template<typename...>
using void_t = void;
template<template<typename...> class, typename, typename, typename EnableT = void>
struct fill_template;
template<template<typename...> class TemplateT, typename TupleT, std::size_t... Is>
struct fill_template<
TemplateT, TupleT, std::index_sequence<Is...>,
void_t<TemplateT<std::tuple_element_t<Is, TupleT>...>>
>
{
using type = TemplateT<std::tuple_element_t<Is, TupleT>...>;
};
template<
template<typename...> class TemplateT, typename TupleT,
std::size_t I, std::size_t N
>
struct fill_template_dispatcher
{
template<typename T, typename = typename T::type>
static constexpr std::true_type test(int) { return {}; }
template<typename T>
static constexpr std::false_type test(long) { return {}; }
using candidate_t = fill_template<TemplateT, TupleT, std::make_index_sequence<I>>;
using type = typename std::conditional_t<
test<candidate_t>(0),
candidate_t,
fill_template_dispatcher<TemplateT, TupleT, I + 1, I != N ? N : 0>
>::type;
};
template<template<typename...> class TemplateT, typename TupleT, std::size_t I>
struct fill_template_dispatcher<TemplateT, TupleT, I, 0>
{
static_assert(I != I, "tuple contains insufficient types to satisfy all templates");
};
} // namespace detail
template<typename TupleT, template<typename...> class... TemplateTs>
struct template_pack
{
static_assert(std::tuple_size<TupleT>::value, "tuple must not be empty");
using type = std::tuple<typename detail::fill_template_dispatcher<
TemplateTs, TupleT, 0, std::tuple_size<TupleT>::value
>::type...>;
};
template<typename TupleT, template<typename...> class... TemplateTs>
using template_pack_t = typename template_pack<TupleT, TemplateTs...>::type;
Online Demo
Note that for variadic class templates this will pass as few types as possible (see D in the test); for an implementation that passes as many types as possible instead, see that variation of the code here (only two lines are changed in the implementation).

Indices trick used for several components

Consider this fully working code:
#include <type_traits>
template <typename T, typename IndexPack> struct Make;
template <typename T, template <T...> class P, T... Indices>
struct Make<T, P<Indices...>> {
using type = P<(Indices+1)..., (-3*Indices)..., (Indices-1)...>;
};
template <int...> class Pack;
int main() {
static_assert (std::is_same<Make<int, Pack<1,2,3,4>>::type,
Pack<2,3,4,5, -3,-6,-9,-12, 0,1,2,3>>::value, "false");
}
What I actually want the output to be is
Pack<2,-3,0, 3,-6,1, 4,-9,2, 5,-12,3>
instead of Pack<2,3,4,5, -3,-6,-9,-12, 0,1,2,3>. I first tried
using type = P<(Indices+1, -3*Indices, Indices-1)...>;
but that is simply understood by the compiler to be a useless comma operator. What is the desired syntax to get what I want? If there is no such syntax, what is the cleanest way to do this, keeping in mind that using Indices 3 times is just an example (we may want to use it more than 3 times). Please don't tell me that I have to write a helper to extract the individual packs and then "interlace" all the elements. That nightmarish method cannot be the best solution (and such a solution would also only work if we knew exactly how many individual packs to extract).
Would defining
template <typename T, template <T...> class P, T I>
struct Component {
using type = P<I+1, -3*I, I-1>;
};
help somehow? Make a pack expansion on this?
Yes, you can concat recursively:
template <typename, typename, typename> struct Concat;
template <typename T, template <T...> class P, T... A, T... B>
struct Concat<T, P<A...>, P<B...>> {
using type = P<A..., B...>;
};
template <typename T, typename IndexPack> struct Make;
template <typename T, template <T...> class P, T... I, T F >
struct Make<T, P<F, I...>> {
using type = typename Concat<T,
typename Make<T, P<F>>::type,
typename Make<T, P<I...>>::type>::type;
};
template <typename T, template <T...> class P, T I>
struct Make<T, P<I>> {
using type = P<I+1, -3*I, I-1>;
};
Demo
This was inspired by Columbo's solution. It uses the pack expansion syntax that I originally sought, namely
using type = typename Merge<T, typename Component<T, P, Indices>::type...>::type;
As a result, now Make is reusable, first using Triple, and then using Quadruple, so any number of usages of Indices can be expanded simultaneously. Here Component is a template-template-template parameter passed into Make:
#include <type_traits>
template <typename T, typename... Packs> struct Merge;
template <typename T, template <T...> class P1, template <T...> class P2, T... Is, T... Js>
struct Merge<T, P1<Is...>, P2<Js...>> {
using type = P1<Is..., Js...>;
};
template <typename T, typename Pack1, typename Pack2, typename... Packs>
struct Merge<T, Pack1, Pack2, Packs...> {
using type = typename Merge<T, Pack1, typename Merge<T, Pack2, Packs...>::type>::type;
};
template <typename T, template <T...> class P, T I>
struct Triple {
using type = P<I+1, -3*I, I-1>;
};
template <typename T, template <T...> class P, T I>
struct Quadruple {
using type = P<I+1, -3*I, I-1, I>;
};
template <typename T, typename IndexPack,
template <typename U, template <U...> class P, U I> class Component> struct Make;
template <typename T, template <T...> class Z, T... Indices,
template <typename U, template <U...> class P, U I> class Component>
struct Make<T, Z<Indices...>, Component> {
using type = typename Merge<T, typename Component<T, Z, Indices>::type...>::type;
};
template <int...> class Pack;
int main() {
static_assert (std::is_same<Make<int, Pack<1,2,3,4>, Triple>::type,
Pack<2,-3,0, 3,-6,1, 4,-9,2, 5,-12,3>>::value, "false");
static_assert (std::is_same<Make<int, Pack<1,2,3,4>, Quadruple>::type,
Pack<2,-3,0,1, 3,-6,1,2, 4,-9,2,3, 5,-12,3,4>>::value, "false");
}

How to make a variadic is_same?

How can I make a class template that returns whether any of its variadic types are equal to the first type. I want to be able to do this:
is_same<T, A, B, C>::value; // true if T is one of A, B or C
And if T is equal to any one of those types, its static value member will be true, otherwise false. How can I do this?
Nice and concise with C++17:
template <class T, class... Ts>
struct is_any : std::disjunction<std::is_same<T, Ts>...> {};
And the dual:
template <class T, class... Ts>
struct are_same : std::conjunction<std::is_same<T, Ts>...> {};
A variation that uses fold expressions:
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> && ...)> {};
Use template recursion:
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
In C++17 you have an even nicer solution, using template variables and fold expressions:
template<class T, class... Rest>
inline constexpr bool are_all_same = (std::is_same_v<T, Rest> && ...);
And the usage is also simpler than all other examples:
are_all_same<T, A, B, C>
No ::value, no parentheses!
Something like this. First, a small metaprogramming library, because it adds like 2 lines to do it generically:
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>
{};
Then a 2 line implementation of is_any_same_to_first:
template<typename... Ts>
using is_any_same_to_first = is_any_to_first< std::is_same, Ts... >;
And for completeness, the original is_all, which may also prove useful:
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 of the is_all_same.
Note that calling is_any_same_to_first anything less explicit is asking for trouble. 2/3 people who tried to answer this question, including me, assumed that is_same<A,B,C> is true iff all three are the same type!
Using the relaxed C++14 constexpr functions, these kinds of things are much easier to code, and probably much faster to compile as well, so you could write:
template <class T, class ... Candidates>
constexpr bool is_all_same() {
bool pairs[] = {std::is_same<T,Candidates>::value...};
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<T,Candidates>::value...};
for(bool p: pairs) if(p) return true;
return false;
}
This is enabled by the fact that in C++14 constexpr functions can have for loops.
The most generic version that works :
since C++11
without dependencies (no #include <type_traits> needed)
only one name is_same works for n-types (no is_same_all needed)
template <typename First, typename Second, typename ... Next>
struct is_same {
template <typename A, typename B>
struct is_same_min {
enum { value = false };
};
template <typename A>
struct is_same_min<A,A> {
enum { value = true };
};
template <typename X, typename Y>
constexpr static bool check() {
return is_same_min<X,Y>::value;
};
template <typename X, typename Y, typename Z, typename ... K>
constexpr static bool check() {
return is_same_min<X,Y>::value and check<Y, Z, K...>();
};
enum { value = check<First, Second, Next...>() };
};
Just use is_same<T1,T2,T3...>::value