C ++ MPL or_, and_ реализации - PullRequest
       18

C ++ MPL or_, and_ реализации

6 голосов
/ 24 декабря 2010

Я пытаюсь прочитать заголовки повышения, чтобы выяснить, как им удалось реализовать

or_<...> 

и

and_<...> 

метафункций так, чтобы:

1) Они могут иметь произвольное количество аргументов (хорошо, скажем, до 5 аргументов)

2) Они имеют поведение короткого замыкания, например:

or_<false_,true_,...> 

не создает экземпляр того, что следует после true_ (поэтому оно также может быть объявлено, но не определено)

К сожалению, метапрограммирование препроцессора делает мою задачу невозможной для меня: P

Заранее благодарю за любую помощь / предложение.

Ответы [ 2 ]

2 голосов
/ 28 декабря 2010

Вот как может работать короткое замыкание для версии с тремя аргументами

template<typename T1, typename T2, typename T2>
struct or_ : conditional<T1::value, true_, or<T2, T3>>::type 
{ };

То есть, если T1::value истинно, оно наследует true_, иначе оно наследует or<T2, T3>. Вам нужен критерий остановки, который работает так, как показывает @begemoth: Specialize or_ для первого типа none_t, который будет определять от ::value до false.

1 голос
/ 24 декабря 2010

Я не опытный в Boost.MPL, поэтому я могу только догадываться, как это действительно реализовано, но у меня есть идеи, как это сделать.

Давайте начнем с вашего первого вопроса. У этого есть два решения, одно для C ++ 98 (с ограниченным числом аргументов) и одно для C ++ 0x. Мы определяем or_ так:


struct null_type { };

template<typename T1 = null_type, typename T2 = null_type, typename T3 = null_type>
struct or_
{
  static const bool value = T1::value || T2::value || T3::value;
};

template<typename T1, typename T2>
struct or_<T1, T2, null_type>
{
  static const bool value = T1::value || T2::value;
};

template<typename T1>
struct or_<T1, null_type, null_type>
{
  static const bool value = T1::value;
};

template<>
struct or_<null_type, null_type, null_type>
{
  static const bool value = false;
};

struct true_ { static const bool value = true; };
struct false_ { static const bool value = false; };

Чтобы получить больше параметров для мета-функции, вам нужно указать больше параметров для шаблона or_. Вы можете генерировать специализации, используя Boost.Preprocessor.

В C ++ 0x вы можете использовать переменные шаблоны:


template<typename... T>
struct or_;

template<>
struct or_<>
{
  static const bool value = false;
};

template<typename T1, typename... Ts>
struct or_<T1, Ts...>
{
  static const bool value = T1::value || or_<Ts...>::value;
};

Это классический рекурсивный список обработки кода. Чтобы ознакомиться с этим стилем, прочитайте кое-что о функциональном программировании.

Второй вопрос проще. Аргументы метафункций or_ и and_ являются типами, т. Е. Нулевыми метафункциями, и они вызываются только тогда, когда необходимы их значения (это семантика логических операторов в C ++). Используя простую функцию, аналогичный код:

bool true_() { return true; }
bool false_() { return false; }

bool or_(bool (*x)(), bool (*y)()) 
{ 
  return x() || y(); 
}
...