3

Given the following C++ typedef expression

template <bool> struct BoolType : std::true_type {};

template <> struct BoolType< false > : std::false_type {};

typedef BoolType< ArgResolver< Arg1 >::IsResolvable::value && ArgResolver< Arg2 >::IsResolvable::value > IsSignatureRecognized;

I was asking myself if it could be done with a variadic template. The code comes from Hypodermic IoC container. How can I unpack them while retaining the && check between each of them?

Stefano
  • 3,213
  • 9
  • 60
  • 101

2 Answers2

4

In C++17, you may do:

using IsSignatureRecognized = BoolType<(ArgResolver<Args>::IsResolvable::value && ...)>;

before, you have to make an variadic 'and' by yourself.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • this is really nice, but I'm compiling on c++11. It was the first thing I tried (except for the using statement instead of typedef) but obviously it didn't compile – Stefano Dec 08 '15 at 16:25
3

Just write up an and_ metafunction like this:

    template <class ... Bools>
    struct and_;

    template <class Bool, class ... Bools>
    struct and_<Bool, Bools...> : std::conditional<
        Bool::value, and_<Bools...>, std::false_type>::type{};

    template <>
    struct and_<> : std::true_type{};

I haven't tested this so there may be a couple of typos, but I hope you get the idea.

Then you use it like this:

    typedef and_<typename ArgResolver<Args>::IsResolvable...> IsSignatureRecognized;

The way it works is fairly simple, we have the generic class template <class...> and_ which accepts any number of types. The first specialization checks the first argument in the pack, if it's false there's no need to continue since the whole and_ will be false. If it's true then we continue checking the rest of the parameters. Once there are no more parameters left, the specialization with no parameters simply returns true.

Here's an example:

and_<t, t, f, t>::value
gives conditional<t::value, and_<t, f, t>, f>::type

Because the condition is true, type evaluates to the second parameter and_<t, f, t>. Similarly for the next parameter, we get to:

and_<f, t>::value
gives conditional<f::value, and_<t>, f>::type

Now the condition is false so type evaluates to the third parameter f and we are done instantiating templates and ::value gives us false.

If all the parameters are true you will eventually reach and_<> which we specialized to be std::true_type so that ::value gives us true.

I hope that helps clarify how this code works.

SirGuy
  • 10,660
  • 2
  • 36
  • 66
  • it works! Could you just explain the code? I'm a newbie and I'm still learning variadic templates, so I didn't really understood what you did – Stefano Dec 08 '15 at 16:17
  • Note that something very similar was added to C++17 called `std::conjunction`. – Simple Dec 08 '15 at 16:25
  • thank you for the explanation, I really appreciate it. @Simple that's really cool, do you know if Visual Studio 2015 supports it? – Stefano Dec 08 '15 at 16:45