C ++ boost :: lambda :: ret эквивалент в Фениксе - PullRequest
3 голосов
/ 19 мая 2010

Boost lambda позволяет перезаписать выведенный тип возврата, используя шаблон ret<T>. Я пытался найти эквивалент в Фениксе, но не смог его найти.

Есть ли эквивалент в Фениксе? Я знаю, как сделать свою собственную замену, но я бы не хотел. спасибо

Ответы [ 2 ]

8 голосов
/ 26 мая 2010

Переписать: я пропустил пункт в моем первом ответе (было поздно), позвольте мне повторить попытку.

Позвольте мне рассказать о таких людях, как я, которые могут упустить вашу мысль в первый раз. В boost :: lambda при использовании пользовательских типов в выражениях операторов необходимо использовать функцию ret <> для отмены вывода возвращаемого типа. Это потому, что система вывода лямбда-возвращаемых типов напрямую поддерживает только нативные (и stl? Я не помню) типы. Краткий пример:

using namespace boost::lambda;

struct add_t{
    add_t(int i) : i(i) {};
    add_t operator+(const add_t& other) const{
        return add_t(i + other.i);
    }
    int i;
};

(_1 + _2)(add_t(38), add_t(4));           // RETURN TYPE DEDUCTION FAILS
ret<add_t>(_1 + _2)(add_t(38), add_t(4)); // OK

Однако в Phoenix подсказки не нужны (обратите внимание, что литералы и неконстантные временные символы не могут появиться в списке аргументов Phoenix):

using namespace boost::phoenix;

add_t i(38), j(4);
(_1 + _2)(i, j);    // JUST FINE

Система дедукции обратного типа совершенно другая и гораздо более естественная в Фениксе; он будет правильно выводить тип возвращаемых операторов, которые используют обычную семантику. В частности, возвращаемый тип должен соответствовать типу одного из операндов, быть ссылкой, указателем или константным указателем на один из типов аргументов или быть итератором контейнера / контейнера stl одного из этих типов. В заголовке type_deduction.hpp есть хорошая запись вывода типа Phoenix для получения более подробной информации.

Итак, сейчас я читаю ваш вопрос: как можно обрабатывать нетрадиционную семантику операторов в Фениксе?

Рассмотрим следующую странную пару типов в качестве примера

struct add_ret_t{
    add_ret_t(int i) : i(i) {};
    int i;
};

struct add_t{
    add_t(int i) : i(i) {};
    add_ret_t operator+(const add_t& other) const{
        return add_ret_t(i + other.i);
    }
    int i;
};

Для лямбды это не проблема, просто используйте функцию ret:

using namespace boost::lambda;

ret<add_ret_t>(_1 + _2)(add_t(38), add_t(4)); // OK

Но Феникс не может справиться с этим оператором (вы можете винить его?), Потому что тип возвращаемого значения не связан с аргументами, и нет способа напрямую указать тип возвращаемого значения в Фениксе. Если есть веская причина для использования такого оператора, такой случай можно добавить в систему дедукции типов, но я не могу найти способ сделать это без взлома type_deduction.hpp или ветвления хорошей части Феникса.

В качестве альтернативы, я решил немного взломать, чтобы переопределить типы возвращаемых данных для определенных операторов. Result_of_ операция шаблонные структуры в boost / spirit / home / phoenix / operator / arithmetic.hpp (строки 39-56 перечисляют типы структур, boost 1.43) выполняют вывод типов при их создании и сохраняют результат , Таким образом, все, что нужно, это предоставить некоторые шаблонные специализации для проблемных операций, которые должны содержать только один typedef, указывающий тип возвращаемого значения. Пример ( кодовая панель для полной версии ):

using namespace boost::phoenix;

namespace boost{ namespace phoenix{

//override add_t addition to give add_ret_t
template <> struct result_of_plus<add_t&, add_t&> { typedef add_ret_t type; };

//override int addition to give char
template <> struct result_of_plus<int&, int&> { typedef char type; };

}}

int main()
{
    add_t i = 1, j = 7;
    std::cout << ((_1 + _2)(i, j)).i << std::endl;

    int k = 51, l = 37;
    std::cout << ((_1 + _2)(k, l)) << std::endl;

    return 0;
}

Это, конечно, не замена, но в некоторых отношениях она лучше, чем глобальная. Если существует много операторов для перегрузки, весь набор операций может быть макросирован.

0 голосов
/ 25 мая 2010

AFAIK, это (или что-то подобное) не поддерживается в Фениксе. Если бы вы описали свой вариант использования, я мог бы помочь, хотя.

...