Pregunta

Lets say I have a metafunction

   template<bool, class L, class R>
   struct IF
   {
       typedef R type; 
   };


   template <class L, class R>
   struct IF<true, L, R>
   {
     typedef L type; 
   };

What I want is to define a metafunction Not that would bind to IF and return the 'opposite state'. What I have so far is this :

template<bool Cond, typename L, typename R, template<bool, typename,typename> class MF>
struct Not
{
    typedef typename MF<!Cond, L, R>::type type;
};

This works for this particular case. My questions are:

  1. Is there a way to provide a more general solution ? (In terms of arguments and functionality of the metafunction we are extending)
  2. Is there a proven desing/idiom/pattern to do these things in C++
  3. I suspect this can be done with boost::mpl. Can anyone provide an example?
¿Fue útil?

Solución

The most general solution I can come up with works with any class template taking a bool and an arbitrary amount of type parameters - including std::enable_if:

template<template<bool, typename...> class T, bool arg1, typename... args>
struct Not : T<!arg1, args...> { };

Simple usage would be:

struct bacon {
    static const bool tasty = true;
    static std::string name() { return "bacon"; }
};

struct spinach {
    static const bool tasty = false;
    static std::string name() { return "spinach"; }
};

template<typename Food>
typename std::enable_if<Food::tasty>::type eat()
{
    ::std::cout << "Yummy! " << Food::name() << "!\n";
}

template<typename Food>
typename Not<std::enable_if, Food::tasty, void>::type eat()
{
    ::std::cout << "Yuck! " << Food::name() << "!\n";
}

And the test case

eat<bacon>();
eat<spinach>();

Will inform you that bacon is tasty, while spinach is not.

Otros consejos

You may make the Not a template with a single parameter:

#include <iostream>

template<bool, class L, class R>
struct IF
{
    typedef R type;
};

template <class L, class R>
struct IF<true, L, R>
{
    typedef L type;
};


template<typename MF>
struct Not;

template<bool Cond, typename L, typename R, template<bool, typename, typename> class MF>
struct Not<MF<Cond, L, R>>
{
    typedef typename MF<!Cond, L, R>::type type;
};

struct A { static void print() { std::cout << "A\n"; } };
struct B { static void print() { std::cout << "B\n"; } };

int main()
{
    IF<true, A, B>::type::print();
    Not<IF<true, A, B>>::type::print();
    return 0;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top