2

Consider the bool trick to check if a bunch of types are all the same type:

template<typename Type, typename... Types>
static constexpr bool allOf = std::is_same<
    std::integer_sequence<bool, true, std::is_same<Type, Types>::value...>,
    std::integer_sequence<bool, std::is_same<Type, Types>::value..., true>
>::value;

As an example, one can use it as it follows to check that all the parameters are int values:

template<typename... Args>
void f(Args&&... args) {
    static_assert(allOf<int, Args...>, "!");
    // ...
}

Is there any way to use it with specializations of a given template template parameter?
As an example, with the following code:

template<typename> struct S {};

template<typename... Args>
void f(Args&&... args) {
    static_assert(allOf<S, Args...>, "!");
    // ...
}

The allOf variable should be defined as:

template<template<typename> class Type, typename... Types>
static constexpr bool allOf = ???;

And I would like to check that each T in Types is a specialization of the form S<U>, no matter of what is U.

Is it possible?

max66
  • 65,235
  • 10
  • 71
  • 111
skypjack
  • 49,335
  • 19
  • 95
  • 187
  • 2
    that bool trick is nice, who came up with this? – Johannes Schaub - litb Feb 18 '17 at 22:38
  • @JohannesSchaub-litb I don't remember where I found it, it was here on SO anyway. The version I ran into was built up using structures, `std::conditional`, `std::true_type` and `std:.false_type`. I started using this one when I discovered variable templates for it's more compact than the original one. – skypjack Feb 18 '17 at 22:43
  • nice trick, anyway – max66 Feb 18 '17 at 22:45
  • 1
    I would not change the bool trick, but call it differently: http://coliru.stacked-crooked.com/a/b6f7bc5bff2b9abc – Johannes Schaub - litb Feb 18 '17 at 22:46
  • @JohannesSchaub-litb That version doesn't work if I do simply `f(0, 1);`. :-( – skypjack Feb 18 '17 at 22:48
  • @skypjack wasn't that the point of it? `int` is not a specialization of `S` so it should fail. Then I don't understand it. – Johannes Schaub - litb Feb 18 '17 at 22:49
  • @JohannesSchaub-litb It doesn't compile at all. The aim is to assign false to the template variable instead. ;-) ... The bool trick above does that: the variable template is true if all types are `Type`, false otherwise. It compiles in both cases. – skypjack Feb 18 '17 at 22:51
  • 2
    @skypjack ah I see now. I think that's because `Unspecialize` doesn't handle non-template classes. Fixed: http://coliru.stacked-crooked.com/a/44c569626866b4c9 – Johannes Schaub - litb Feb 18 '17 at 22:52
  • @JohannesSchaub-litb I like your solution. Feel free to put it in an answer. That's a good candidate for acceptanc, for it doesn't require me to change the trick itself. – skypjack Feb 18 '17 at 22:54
  • 1
    @JohannesSchaub-litb I'm used to crediting [Columbo](http://stackoverflow.com/a/28253503/3233393) for this one, it's where I've seen it first. – Quentin Feb 18 '17 at 23:06
  • 1
    @Quentin Thanks. I didn't succeed in finding it. Anyway the one I saw was slightly different, but I agree on crediting Columbo on trust. :-) – skypjack Feb 18 '17 at 23:10
  • @Quentin Not saying it wasn't Columbo, but non-recursive versions exists for a bit longer than the answer from Columbo you linked, e.g., http://stackoverflow.com/a/24687161/2073257 – Daniel Frey Feb 19 '17 at 09:51

2 Answers2

5

We just need a check for a specialization:

template <class T, template <class...> class Z>
struct isZ : std::false_type { };

template <class... Args, template <class...> class Z>
struct isZ<Z<Args...>, Z> : std::true_type  { };

And a more generic implementation of allOf:

template <bool... bs>
using allOf = std::is_same<
    std::integer_sequence<bool, true, bs...>,
    std::integer_sequence<bool, bs..., true>>;

With that:

static_assert(allOf<isZ<decay_t<Args>, S>::value...>::value, "!");
Barry
  • 286,269
  • 29
  • 621
  • 977
1

What about as follows ?

template <typename>
struct S
 { };

template <template <typename> class, typename>
struct isS
 { static constexpr bool value { false } ; };

template <template <typename> class S, typename U>
struct isS<S, S<U>>
 { static constexpr bool value { true } ; };

template<template<typename> class Type, typename... Types>
static constexpr bool allOf = std::is_same<
    std::integer_sequence<bool, true, isS<Type, Types>::value...>,
    std::integer_sequence<bool, isS<Type, Types>::value..., true>
>::value;
max66
  • 65,235
  • 10
  • 71
  • 111