mercredi 19 juillet 2017

Variadic template for compile-time type selection based on condition

In trying to better understand variadic templates, I set myself the task of writing a compile-time type selector based on a given condition (chosen among the ones defined in <type_traits>, e.g. std::is_signed, std::is_floating_point etc.). The selector should pick the first type that meets the condition among those specified as template arguments.

To give you an example:

template<template<typename> class Cond, typename... T> 
struct first_if_any {
    // some code here
};

first_if_any<std::is_signed, unsigned, long, int>::type a; // long
first_if_any<std::is_unsigned, short, unsigned long, unsigned>::type b; // unsigned long
first_if_any<std::is_floating_point, int, float, double>::type c; // float

These are the features I'd like my selector to have:

  1. choose the first type if no type meets the condition
  2. print a user-friendly compilation error if no types are specified

Thus:

first_if_any<std::is_unsigned, long, int>::type a; // long
first_if_any<std::is_arithmetic>::type b; // ERROR

Here's what I came up with (see working example here):

template<template<typename> class Cond, typename... T> 
struct first_if_any {
    using type = void;
    static constexpr bool found = false;
};

template<template<typename> class Cond, typename First, typename... T> 
struct first_if_any<Cond, First, T...> {
    using type = typename std::conditional<Cond<First>::value || !first_if_any<Cond, T...>::found, First, typename first_if_any<Cond, T...>::type>::type;
    static constexpr bool found = Cond<First>::value || first_if_any<Cond, T...>::found;
};

This selects types as expected, and meets requirement 1. Now for my questions:

  • How can I meet requirement 2, i.e. generate a user-friendly compile error if someone tries to use the selector without passing types to it?
  • Is there a better way to do this (using only standard library features)?

Bonus question, if anyone cares to elaborate:

  • Does this qualify as template metaprogramming?

Aucun commentaire:

Enregistrer un commentaire