user1244932
user1244932

Reputation: 8142

How to combine conditions from type_traits the standard way

For example, I want to use type T only if std::is_pointer<T> and std::is_const<T> evaluate to true_type.

Of course, there is a simple way like this:

template <typename T>
void f(T t, std::true_type, std::true_type) {}
template <typename T>
void f(T t)
{
  f(t, std::is_pointer<T>{}, std::is_const<T>{});
}

But I want something like this:

template <typename T>
void f(T t, std::true_type) {}
template <typename T>
void f(T t)
{
  f(t, std::and<std::is_pointer<T>, std::is_const<T>>{});
}

Does the Standard Library contain something like std::and? If not, is there a simple way to implement it with the desired functionality?

Upvotes: 12

Views: 3471

Answers (2)

Nikos Athanasiou
Nikos Athanasiou

Reputation: 31549

With the advent of C++17 conjunction and disjunction you could easily compose for variadic (number of) predicates:

template <class T, template <class> class... Ps>
constexpr bool satisfies_all_v = std::conjunction<Ps<T>...>::value;

template <class T, template <class> class... Ps>
constexpr bool satisfies_any_v = std::disjunction<Ps<T>...>::value;

And this is how you'd use it:

satisfies_all_v<T, is_pointer, is_const>

Demo

Upvotes: 8

TartanLlama
TartanLlama

Reputation: 65710

You can simply && together the results of the traits and put them in a std::integral_constant:

std::integral_constant<bool, 
                       std::is_pointer<T>::value && std::is_const<T>::value>

Or you can write a generic trait and. Some possibilities from here:

Option 1:

template<typename... Conds>
  struct and_
  : std::true_type
  { };

template<typename Cond, typename... Conds>
  struct and_<Cond, Conds...>
  : std::conditional<Cond::value, and_<Conds...>, std::false_type>::type
  { };

//usage
and_<std::is_pointer<T>, std::is_const<T>>

Option 2:

template<bool...> struct bool_pack;
template<bool... bs> 
using and_ = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;

//usage
and_<std::is_pointer<T>, std::is_const<T>>

When we get fold expressions you'll be able to do this:

template<typename... Args>
using and_ = std::integral_constant<bool, (Args::value && ...) >;

Your compiler may already support this under the -std=c++1z flag like this.

Upvotes: 16

Related Questions