Я не опытный в 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();
}