Checking if variadic template parameters are unique using fold expressions - c++

Given a variadic template parameter pack, I want to check if all types given to it are unique using an inline constexpr bool and fold expressions. I trie something like this:
template<class... T>
inline static constexpr bool is_unique = (... && (!is_one_of<T, ...>));
Where is_one_of is a similar bool that works correctly.
But this line doesn't compile regardless of what I put into is_one_of. Can this even be done using fold expressions, or do I need to use a regular struct for this purpose?

You approach doesn't really work because is_one_of needs to be called with a type T and all the remaining types not including T. There's no way of expressing that with a fold expression over a single parameter pack. I suggest using specialization instead:
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...>
>{};
Usage:
static_assert(is_unique<>);
static_assert(is_unique<int>);
static_assert(is_unique<int, float, double>);
static_assert(!is_unique<int, float, double, int>);
live example on wandbox.org
(Thanks to Barry for the simplification that uses a fold expression.)

-- EDIT --
googling I've found an interesting solution that give me inspiration to avoid recursion and to avoid a lot of warnings
So you can define a wrapper of type
template <typename>
struct wrapT
{ };
and a wrapper for type and integer that inherit from the wrapper for type
template <typename T, std::size_t>
struct wrapTI : public wrapT<T>
{ };
Next you can define a foo class that recursively inherit from wrapTI
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>...
{ };
Now is_unique can be something like
template <typename ... Ts>
static constexpr bool isUnique
= ( ... && std::is_convertible<foo<std::tuple<Ts...>>, wrapT<Ts>>::value );
The point is that foo<Ts...> can be converted to wrapT<T> only if foo<Ts...> inherit one time (and only one time) from wrapT<T>, that is if T is present one time (and only one time) in Ts....
The following is a full compiling example
#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> );
}

Related

is it possible to generate a set of template classes by using another template and recursion?

I want to create a few template classes in order to assert certain type of data:
assertType { static constexpr bool v{false}; };
template<> struct assertType<int> { static constexpr bool v{true}; };
template<> struct assertType<bool> { static constexpr bool v{true}; };
template<>struct assertType<float> { static constexpr bool v{true}; };
template<>struct assertType<long> { static constexpr bool v{true}; };
However, I would like to do it programmatically, So I thought about defining a "list" of the supported types:
template<typename ...Types>
struct TypesList { };
static inline TypesList<int, bool, float, long> supportedTypes;
And have that "list" passed to another template that, by recursion, generates the "assertType" template for every type in the list. Something like:
template<typename ...Ts>
struct BuildTemplates { };
template<typename ...Ts>
struct BuildTemplates<TypesList<Ts...>> { };
BuildTemplates<supportedTypes> /* Build the templates for int, bool, float and long */
So I can use:
assertType<int>::v // v should be true
assertType<bool>::v // v should be true
assertType<float>::v // v should be true
assertType<long>::v // v should be true
Any other template whose type is not one of those, should have its v value set to false.
Is this possible?
Thanks in advance.
The answer mostly depends on the syntax you want to get. For example, you could do this:
#include <type_traits>
template<typename... Types> struct TypeList {};
using SupportedTypes = TypeList<int, bool, float, long>;
template<typename T>
struct assertType {
template<class... Types>
static constexpr bool contains(TypeList<Types...>) {
return (std::is_same_v<T, Types> || ...);
}
static constexpr bool v = contains(SupportedTypes{});
};
static_assert( assertType<int>::v);
static_assert( assertType<bool>::v);
static_assert(!assertType<short>::v);
If you can use boost, boost::mp11::mp_contains could be employed to make the implementation trivial:
#include <boost/mp11.hpp>
using SupportedTypes = boost::mp11::mp_list<int, bool, float, long>;
template<typename T>
struct assertType : boost::mp11::mp_contains<SupportedTypes, T> {};
static_assert( assertType<int>::value);
static_assert( assertType<bool>::value);
static_assert(!assertType<short>::value);
Or if you want to use v instead of value (which is de facto a standard name):
template<typename T>
struct assertType {
static constexpr bool v =
boost::mp11::mp_contains<SupportedTypes, T>::value;
};
This is only possible if your programmatic solution is allowed to define a template specialization of assertType, or to be used within its template definition.
Here's an approach by defining a single partial template specialization of assertType in c++11:
template <typename>
struct assertType { static constexpr bool v = false; };
template <typename...>
struct TypeList {};
using supportedTypes = TypesList<int, bool, float, long>;
#include <type_traits>
template <typename...>
struct any_of : std::false_type {};
template <typename T, typename U, typename... Us>
struct any_of<T, TypeList<U, Us...>> : any_of<T, TypeList<Us...>> {};
template <typename T, typename... Us>
struct any_of<T, TypeList<T, Us...>> : std::true_type {};
template <typename T>
struct assertType<typename std::enable_if<any_of<T, supportedTypes>, T>::type> {
static constexpr bool v = true;
};
You could also just use it within the class template definition itself rather than defining a partial specialization:
// assuming supportedTypes and any_of have already been defined
template <typename T>
struct assertType { static constexpr bool v = any_of<T, supportedTypes>::value; };
In c++17 the definition of any_of becomes much simpler with a fold expression and std::bool_constant:
#include <type_traits>
template <typename...>
struct any_of : std::false_type {};
template <typename T, typename... Us>
struct any_of<T, TypeList<Us...>> : std::bool_constant<(... || std::is_same_v<T, Us>)> {};
Or by using std::disjunction:
#include <type_traits>
template <typename...>
struct any_of : std::false_type {};
template <typename T, typename... Us>
struct any_of<T, TypeList<Us...>> : std::disjunction<std::is_same_v<T, Us>...> {};
Finally in c++20, you can simplify the definition of the assertType partial template specialization using concepts:
// assuming supportedTypes and any_of have already been defined
template <typename T, typename L>
concept any_of_v = any_of<T, L>::value;
template <typename>
struct assertType { static constexpr bool v = false; };
template <any_of_v<supportedTypes> T>
struct assertType<T> { static constexpr bool v = true; };
Except for instantiating a template or preprocessor trickery, there is no way to generate declarations in C++ automatically. Each declaration must be written out explicitly.
But there is no need to have an explicit specialization for each type in the list. You can simply use a single primary template for assertType and set the v member according to membership in the list or you can use a fixed number of partial specializations. The other answers give approaches to do this.

Template metaprogram to find similar consecutive typenames

I am new to template meta programming and was trying to create a program that would find if a parameter pack has consecutive same type names. For example <int, int>, <int, char, char> would return true and <int,char> and <int, char, int> would not.
I managed to write this piece of code but it seems to be comparing each value of parameter pack with itself. I am just looking for a way to iterate through the values of parameter pack to compare with it's consecutive element.
template<typename T, typename U>
struct sameTypename{
enum {value = false};
};
template<typename T>
struct sameTypename<T, T>{
enum {value = true};
};
template <typename T, typename ...args>
struct consTypename{
enum {value = (sameTypename<consTypename<args...>, consTypename<args...>>::value)};
};
template <typename T>
struct consTypename<T, T>{
enum {value = true};
};
template <typename T>
struct consTypename<T>{
enum {value = false};
};
Here you go:
#include <type_traits>
template <typename ...P> struct has_adjacent_same_types : std::false_type {};
template <typename A, typename B, typename ...P> struct has_adjacent_same_types<A, B, P...>
: std::bool_constant<std::is_same_v<A,B> || has_adjacent_same_types<B, P...>::value> {};
I used : std::false_type {}; and : std::bool_constant<X> {}; instead of
{enum{value = false};}; and {enum{value = X};}; respectively, but that's simply a matter of preference.
Some of the features I used are from C++17. If you're using an older version, note that:
std::bool_constant and std::is_same_v are available only starting from C++17 (but that you can use std::integral_constant and std::is_same<>::value before).
(c) #max66
A variation of the HolyBlackCat's solution.
template <typename ...>
struct has_adjacent_same_types : public std::false_type
{ };
template <typename T0, typename ... Ts>
struct has_adjacent_same_types<T0, T0, Ts...> : public std::true_type
{ };
template <typename T0, typename T1, typename ... Ts>
struct has_adjacent_same_types<T0, T1, Ts...>
: public has_adjacent_same_types<T1, Ts...>
{ };
Two simpler specializations instead of only one, more complex.
Substantially is the same things (I suppose) but I find it a little clear to read and understand.
I propose also a completely different solution that uses template folding (so only C++17 or newer, unfortunately) instead of template recursion.
template <typename...>
struct sae_helper;
template <typename ... Ts, typename ... Us>
struct sae_helper<std::tuple<Ts...>, std::tuple<Us...>>
: public std::bool_constant<(std::is_same_v<Ts, Us> || ...)>
{ };
template <typename ... Ts>
struct some_adjacent_equal
: public sae_helper<std::tuple<void, Ts...>, std::tuple<Ts..., void>>
{ };
If void is a possible type in the list of type to check, calling sae_helper from some_adjacent_equal instead of void must be used a different type, obviously.
I suppose that this solution is preferable, over a recursive one, when the list of types is very long because avoid compilers template-recursion limits.
If you can use C++14, you can use a constexpr function instead of template folding (and a tag-type instead of void) as follows
template <typename ... Ts, typename ... Us>
constexpr bool sae_helper (std::tuple<Ts...> const &,
std::tuple<Us...> const &)
{
using unused = bool[];
bool ret { false };
(void)unused { true, ret |= std::is_same<Ts, Us>::value... };
return ret;
}
struct no_type
{ };
template <typename ... Ts>
struct some_adjacent_equal
: public std::integral_constant<bool, sae_helper(std::tuple<no_type, Ts...>{},
std::tuple<Ts..., no_type>{})>
{ };
but, this way, you loose short-circuiting in or evaluation.

Exclude first n arguments from parameter pack

I have a function foo that calls a function bar with a subset of types passed into foo's variadic template. For example:
template <typename... T>
void foo() {
// ...
template <size_t start_idx, typename... T>
using param_pack = /*Parameter pack with T[start_idx]...T[N]*/
auto b = bar<param_pack<2, T...>>();
// ...
}
Is there a way to extract a "sub-parameter pack". In the above case
if T = [int float char double] then param_pack<2, T...> = [char double]
[EDIT]
My goal is to be able to use something like this to match event handlers. For example
struct ev {};
template <typename... T>
struct event : ev {
std::tuple<T...> data_;
event(T&&... d) : data_(std::make_tuple(std::forward<T>(d)...)) {}
};
template <typename... Functor>
struct handler {
std::tuple<Functor...> funcs_;
handler(Functor&&... f) : funcs_(std::make_tuple(std::forward<Functor>(f)...)) {}
void handle_message(ev* e) {
auto ptrs = std::make_tuple(
dynamic_cast<event<param_pack<1, typename function_traits<F>::args>>*>(e)...
);
match(ptrs);
}
};
Here function_traits::args get a parameter pack for the function arguments and match iterates over the the tuple funcs_ checking if the dynamic_cast was successful and executing the first successful function. I already have these implemented.
The handlers are something like
[] (handler* self, <ARGS>) -> void {
// ...
}
I am essentially trying to get rid of the self argument.
Set aside the fact that it lacks a check on the index N for simplicity, here is a possible solution based on a function declaration (no definition required) and an using declaration:
template<std::size_t N, typename... T, std::size_t... I>
std::tuple<std::tuple_element_t<N+I, std::tuple<T...>>...>
sub(std::index_sequence<I...>);
template<std::size_t N, typename... T>
using subpack = decltype(sub<N, T...>(std::make_index_sequence<sizeof...(T) - N>{}));
The good part of this approach is that you have not to introduce a new type designed around a tuple, then specialize it somehow iteratively.
It follows a minimal, working example that uses the code above:
#include<functional>
#include<tuple>
#include<cstddef>
#include<type_traits>
template<std::size_t N, typename... T, std::size_t... I>
std::tuple<std::tuple_element_t<N+I, std::tuple<T...>>...>
sub(std::index_sequence<I...>);
template<std::size_t N, typename... T>
using subpack = decltype(sub<N, T...>(std::make_index_sequence<sizeof...(T) - N>{}));
int main() {
static_assert(std::is_same<subpack<2, int, float, char, double>, std::tuple<char, double>>::value, "!");
}
See a full example up and running on wandbox.
The extended version that includes a check on the index N would look like this:
template<std::size_t N, typename... T, std::size_t... I>
std::enable_if_t<(N < sizeof...(T)), std::tuple<std::tuple_element_t<N+I, std::tuple<T...>>...>>
sub(std::index_sequence<I...>);
That is the type you can see in the first example once wrapped in a std::enable_if_t, nothing more. Again, declaration is enough, no definition required.
EDIT
If you want to use your own class template instead of an std::tuple, you can easily modify the code to do that:
#include<functional>
#include<tuple>
#include<cstddef>
#include<type_traits>
template<typename...>
struct bar {};
template<template<typename...> class C, std::size_t N, typename... T, std::size_t... I>
std::enable_if_t<(N < sizeof...(T)), C<std::tuple_element_t<N+I, std::tuple<T...>>...>>
sub(std::index_sequence<I...>);
template<template<typename...> class C, std::size_t N, typename... T>
using subpack = decltype(sub<C, N, T...>(std::make_index_sequence<sizeof...(T) - N>{}));
int main() {
static_assert(std::is_same<subpack<bar, 2, int, float, char, double>, bar<char, double>>::value, "!");
}
EDIT
According to the code added to the question, the solution above is still valid. You should just define your event class as it follows:
struct ev {};
template <typename>
struct event;
template <typename... T>
struct event<std::tuple<T...>>: ev {
// ...
};
This way, when you do this:
event<param_pack<1, typename function_traits<F>::args>>
You still get a tuple out of param_pack (that is the subpack using declaration in my example), but it matches the template partial specialization of event and the parameter pack is at your disposal as T....
This is the best you can do, for you cannot put a parameter pack in an using declaration. Anyway it just works, so probably it can solve your issue.
You may do something like:
template <std::size_t N, typename ... Ts> struct drop;
template <typename ... Ts>
struct drop<0, Ts...>
{
using type = std::tuple<Ts...>;
};
template <std::size_t N, typename T, typename ... Ts>
struct drop<N, T, Ts...>
{
using type = typename drop<N - 1, Ts...>;
};
// Specialization to avoid the ambiguity
template <typename T, typename... Ts>
struct drop<0, T, Ts...>
{
using type = std::tuple<T, Ts...>;
};
Here is a quick but not particularly reusable solution.
template <typename Pack, std::size_t N, std::size_t... Is>
void invoke_bar_impl(std::index_sequence<Is...>) {
bar<std::tuple_element_t<N + Is, Pack>...>();
}
template <std::size_t N, typename... Ts>
void invoke_bar() {
auto indices = std::make_index_sequence<sizeof...(Ts) - N>();
invoke_bar_impl<std::tuple<Ts...>, N>(indices);
}

Find number of unique values of a parameter pack

Given a parameter pack with variadic arguments, how can one find the number of unique values in the pack. I am looking for something along the lines of
no_of_uniques<0,1,2,1,2,2>::value // should return 3
My rudimentary implementation looks something this
template <size_t ... all>
struct no_of_uniques;
// this specialisation exceeds -ftemplate-depth as it has no terminating condition
template <size_t one, size_t ... all>
struct no_of_uniques<one,all...> {
static const size_t value = no_of_uniques<one,all...>::value;
};
template <size_t one, size_t two, size_t three>
struct no_of_uniques<one,two,three> {
static const size_t value = (one==two && one==three && two==three) ? 1:
(one!=two && two==three) ? 2:
(one==two && one!=three) ? 2:
(one==three && two!=three) ? 2: 3;
};
template <size_t one, size_t two>
struct no_of_uniques<one,two> {
static const size_t value = one==two ? 1: 2;
};
template <size_t one>
struct no_of_uniques<one> {
static const size_t value = 1;
};
Here, I have specialised for up to three arguments but understandably the code grows exponentially with the number of arguments. I would like to have a meta solution for this using solely STL and no third party libraries like Boost.MPL.
A similar question albeit in the context of checking unique types, rather than finding number of unique values of parameter pack can be found here:
Check variadic templates parameters for uniqueness
In the process of finding the number of unique values of a parameter pack, we might need to sort the pack first, and an excellent implementation of that is provided in this other question
Quick sort at compilation time using C++11 variadic templates
Here's a simple O(n^2) way to do it
template <size_t...>
struct is_unique : std::integral_constant<bool, true> {};
template <size_t T, size_t U, size_t... VV>
struct is_unique<T, U, VV...> : std::integral_constant<bool, T != U && is_unique<T, VV...>::value> {};
template <size_t...>
struct no_unique : std::integral_constant<size_t, 0> {};
template <size_t T, size_t... UU>
struct no_unique<T, UU...> : std::integral_constant<size_t, is_unique<T, UU...>::value + no_unique<UU...>::value> {};
So using your example:
no_unique<0, 1, 2, 1, 2, 2>::value; // gives 3
Most of this is machinery I already wrote for a different question, stripped of the "counting" part.
A pack with a sizeof shortcut:
template<class... Ts> struct pack {
static constexpr size_t size = sizeof...(Ts);
};
Add a type to a pack of types, but only if it doesn't exist already:
template<class T, class PT> struct do_push;
template<class T, class...Ts>
struct do_push<T, pack<Ts...>>{
using type = std::conditional_t<std::disjunction_v<std::is_same<Ts, T>...>,
pack<Ts...>,
pack<T, Ts...>
>;
};
template<class T, class PT> using push = typename do_push<T, PT>::type;
Now make a pack of unique types:
template<class P, class PT = pack<> >
struct unique_types_imp { using type = PT; };
template<class PT, class T, class... Ts>
struct unique_types_imp <pack<T, Ts...>, PT>
: unique_types_imp <pack<Ts...>, push<T, PT>> {};
template<class P>
using unique_types = typename unique_types_imp<P>::type;
Finally:
template<size_t S>
using size_constant = std::integral_constant<size_t, S>;
template<size_t... all>
struct no_of_uniques{
static constexpr size_t value = unique_types<pack<size_constant<all>...>>::size;
};
Using Boost.Mp11, this is a short one-liner (as always):
template <size_t... Ns>
using no_of_uniques = mp_size<mp_unique<mp_list<mp_size_t<Ns>...>>>;
Following the same logic as described below. We lift the values into types, put them in a type list, get the unique types out of that, and then get the length.
I'll generalize to types - since metaprogramming works better in types. The algorithm for counting uniqueness is an empty argument list has 0 unique types, and a non-empty list has 1 unique type + the number of unique types in the tail of that list after having removed the initial type.
In fact, let's generalize further than that - let's write a metafunction that takes a list of types and returns the unique types in it. Once you have the unique types, it's easy to count them.
template <class... > struct typelist { };
template <class >
struct uniq;
template <class TL>
using uniq_t = typename uniq<TL>::type;
template <>
struct uniq<typelist<>> {
using type = typelist<>;
};
template <class T, class... Ts>
struct uniq<typelist<T, Ts...>>
: concat<typelist<T>, uniq_t<filter_out_t<T, typelist<Ts...>>>>
{ };
Now we just need to fill in concat and filter_out_t. The latter is basically a glorified concat anyway:
template <class... > struct concat;
template <> struct concat<> { using type = typelist<>; };
template <class... Ts>
struct concat<typelist<Ts...>> {
using type = typelist<Ts...>;
};
template <class... Ts, class... Us, class... Args>
struct concat<typelist<Ts...>, typelist<Us...>, Args...>
: concat<typelist<Ts..., Us...>, Args...>
{ };
template <class T, class TL>
struct filter_out;
template <class T, class TL>
using filter_out_t = typename filter_out<T, TL>::type;
template <class T, class... Ts>
struct filter_out<T, typelist<Ts...>>
: concat<
std::conditional_t<std::is_same<T, Ts>::value, typelist<>, typelist<Ts>>...
>
{ };
Now, given a list of types, we can figure out the unique ones. To backport to the original problem, we just need a a size metafunction:
template <size_t N>
using size_t_ = std::integral_constant<size_t, N>;
template <class > struct length;
template <class T> using length_t = typename length<T>::type;
template <class... Ts>
struct length<typelist<Ts...>>
: size_t_<sizeof...(Ts)>
{ };
And then wrap everything up in one alias:
template <size_t... Ns>
using no_of_uniques = length_t<uniq_t<typelist<size_t_<Ns>...>>>;

Checking type of parameter pack using enable_if

Since there is a restriction on allowed non-type variadic templates, I am trying to write a function taking an arbitrary number of doubles using enable_if. In essence, I want to do something like:
template<typename... T,
typename = typename std::enable_if<std::is_convertible<T, double>::value, T>::type>
foo(T... t){ /* code here */ }
I'm opting to put the enable_if as a default value for an unnamed parameter since my function is actually a constructor and will not have a return value. This would work for a single parameter, but as it's a variadic template T is a parameter pack, and the above code is not valid. So, how can I check every parameter is convertible to a double?
The bool_pack trick again.
template<bool...> struct bool_pack;
template<bool... bs>
using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;
Then
template<class R, class... Ts>
using are_all_convertible = all_true<std::is_convertible<Ts, R>::value...>;
and finally
template<typename... T,
typename = typename enable_if<are_all_convertible<double, T...>::value>::type>
foo(T... t){ /* code here */}
You could use fold expression in c++17 to do the same thing as other answers posted here but without the hassle of creating templates.
#include <type_traits>
template <typename... T, typename =
typename std::enable_if<
(true && ... && std::is_convertible_v<T, ___YOUR_TYPE___>),
void
>::type
>
constexpr auto foo(T...) noexcept {
// your code
}
And if you have access to C++20, you can use concepts:
#include <type_traits>
template <typename... T>
requires(
(... && std::is_convertible_v<T, ___YOUR_TYPE___>)
)
constexpr auto foo(T...) noexcept {
// your code
}
I think the simpler would be to use std::initializer_list:
foo(std::initializer_list<double> args)
{
// Your stuff.
}
instead of variadic template.
It may require to use {} instead of/ in addition to ()
Here is another (c++11) version (heavily inspired by the T.C.'s one above):
#include <type_traits>
template <typename To, typename From, typename... R>
struct are_all_convertible {
constexpr static bool value = std::is_convertible<From,To>::value &&
are_all_convertible<To,R...>::value;
};
template <typename To, typename From>
struct are_all_convertible<To,From> {
constexpr static bool value = std::is_convertible<From,To>::value;
};
template<typename... T,
typename = typename std::enable_if<are_all_convertible<double, T...>::value>::type>
foo(T... t){ /* code here */}
Here is a generic approach – a TMP for binary folding, using C++14. First, let's define the basic combining operations:
#include <type_traits>
struct and_op
{
using type = bool;
using identity = std::true_type;
template <bool A, bool B> static constexpr bool value = A && B;
};
struct or_op
{
using type = bool;
using identity = std::false_type;
template <bool A, bool B> static constexpr bool value = A || B;
};
Now the actual fold mechanic:
template <typename Op, typename Op::type...>
struct fold;
template <typename Op>
struct fold<Op> : Op::identity {};
template <typename Op, typename Op::type Val>
struct fold<Op, Val>
: std::integral_constant<typename Op::type
, Val> {};
template <typename Op, typename Op::type Val, typename Op::type... Tail>
struct fold<Op, Val, Tail...>
: std::integral_constant<typename Op::type
, Op::template value<Val, fold<Op, Tail...>::value>> {};
Next, we need a way to create unary traits from binary traits by binding:
template <template <typename, typename> class BPred, typename T>
struct bind_pred
{
template <typename U>
struct pred_1st : std::integral_constant<bool, BPred<T, U>::value> {};
template <typename U>
struct pred_2nd : std::integral_constant<bool, BPred<U, T>::value> {};
};
Finally, a helper wrapper to combine the result of applying a unary predicate:
template <typename Op, template <typename> class UPred, typename ...Args>
struct fold_pred : fold<Op, UPred<Args>::value...> {};
That's it. Now let's get to work:
template <typename T>
using maybe_double = bind_pred<std::is_convertible, double>::pred_2nd<T>;
#include <iomanip>
#include <iostream>
int main()
{
std::cout
<< std::boolalpha
<< fold_pred<and_op, maybe_double, int, float>::value << '\n'
<< fold_pred<and_op, maybe_double, int, float, void>::value << '\n';
}
In C++17 (or C++1z, rather), you can write direct solutions with less code thanks to the new fold expressions. For example:
template <template <typename> class UPred, typename ...Args>
static constexpr bool pred_all = (UPred<Args>::value && ...);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unary fold
Usage:
static_assert(pred_all<maybe_double, int, float>);