Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> как получить сигнатуру лямбда-функции? 
V
    Опции темы
Abyx
Дата 22.7.2010, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



сабж.

Надо получить типы аргументов из любого Callable, в том числе лямбда-функций С++0х.
boost.function_traits с ними не работает.

------------

Код

template<typename T> struct print;

template<typename Callable>
void tester(Callable f)
{
    print<Callable>();
}

int main()
{
    tester([](int x){return x * 2;});
}

выдает
Callable=`anonymous-namespace'::<lambda0>

использовать преобразование в function не хочется, т.к. надо  2 раза писать сигнатуру
Код

tester(std::function<int(int)>([](int x){return x * 2;}));



Это сообщение отредактировал(а) Abyx - 22.7.2010, 19:33
PM MAIL   Вверх
Abyx
Дата 22.7.2010, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



почитал стандарт. лямбда-выражение должно выдавать функтор.

удалось вытащить operator()
Код

print<decltype(&Callable::operator())>();

T=int (__thiscall `anonymous-namespace'::<lambda0>::* )(int) const
PM MAIL   Вверх
Abyx
Дата 22.7.2010, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



непонятно только что написать чтобы заставить работать boost.function_traits или аналог

Это сообщение отредактировал(а) Abyx - 22.7.2010, 15:21
PM MAIL   Вверх
Abyx
Дата 22.7.2010, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



вобщем надо что-то вроде этого
Код

template<typename T> struct print;

#include <type_traits>
#include <boost/function_types/parameter_types.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/at.hpp>

// вынесено в отдельный структ чтобы спрятать decltype 
template<bool isClass, typename T>
struct sw
{
    typedef T type;
};
template<typename T>
struct sw<true, T>
{
    typedef decltype(&T::operator()) type;
};

template<typename T, int N>
struct param
{
    typedef
        typename boost::mpl::at<
            typename boost::function_types::parameter_types<        
                typename sw<
                    std::is_class<T>::value,
                    T
                >::type
            >::type,
            boost::mpl::int_<N - std::is_class<T>::value ? 0 : 1>
        >::type type;
};

template<typename Callable>
void tester(Callable f)
{
    print<param<Callable, 1>::type>();
}

int bar(int x) {return x * 2;}

int main()
{
    tester([](int x){return x * 2;});
    //tester(&bar);
}

PM MAIL   Вверх
boostcoder
Дата 22.7.2010, 18:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(Abyx @ 22.7.2010,  12:10)
сабж.

boost.function_traits не работает

Код

template<typename T> struct print;

template<typename Callable>
void tester(Callable f)
{
    print<Callable>();
}

int main()
{
    tester([](int x){return x * 2;});
}

выдает
Callable=`anonymous-namespace'::<lambda0>

использовать преобразование в function не хочется, т.к. надо  2 раза писать сигнатуру
Код

tester(std::function<int(int)>([](int x){return x * 2;}));

не пойму, что ты хочешь получить... что нужно? опиши детально.
PM WWW   Вверх
Abyx
Дата 22.7.2010, 19:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



boostcoder, мне надо получить типы аргументов из любого Callable
PM MAIL   Вверх
boostcoder
Дата 22.7.2010, 19:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(Abyx @ 22.7.2010,  19:31)
boostcoder, мне надо получить типы аргументов из любого Callable

не сигнатуру функции/метода?
не очень понимаю задачу целиком...
PM WWW   Вверх
Abyx
Дата 22.7.2010, 19:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



задача целиком
Код

#pragma once

// UserHandlerWrapper class
// Generates wrappers for user request handlers

#include <functional>
#include <map>
#include <string>
#include <boost/lexical_cast.hpp>

#include <boost/function_types/parameter_types.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>

namespace WebUI { namespace Impl {

    class UserHandlersWrapper
    {
        typedef std::map<std::string, std::string> args_t;

    public:
        typedef UserHandlersWrapper this_t;

        UserHandlersWrapper() { /* DefaultConstructible */ }

// note that we can't use args[name##i] because args is const
#define ARG(i) boost::lexical_cast<boost::mpl::at<params_t, boost::mpl::int_<i-1>>::type>(args.find(name##i)->second)

        template<typename Callable>
        this_t& operator()(const std::string& path, Callable handler)
        {
            handlers_[path] = [](const args_t&) { return boost::lexical_cast<std::string>(handler()); };
            return *this;
        }
        template<typename Callable>
        this_t& operator()(const std::string& path, Callable handler,
            const char* name1)
        {
            typedef boost::function_types::parameter_types<Callable>::type params_t;
            handlers_[path] = [=](const args_t& args) { return boost::lexical_cast<std::string>(handler(
                ARG(1))); };
            return *this;
        }
        template<typename Callable>
        this_t& operator()(const std::string& path, Callable handler,
            const char* name1, const char* name2)
        {
            typedef boost::function_types::parameter_types<Callable>::type params_t;
            handlers_[path] = [=](const args_t& args) { return boost::lexical_cast<std::string>(handler(
                ARG(1), ARG(2))); };
            return *this;
        }
        template<typename Callable>
        this_t& operator()(const std::string& path, Callable handler,
            const char* name1, const char* name2, const char* name3)
        {
            typedef boost::function_types::parameter_types<Callable>::type params_t;
            handlers_[path] = [=](const args_t& args) { return boost::lexical_cast<std::string>(handler(
                ARG(1), ARG(2), ARG(3))); };
            return *this;
        }
        // TODO: add more overloads

#undef ARG

        bool HasHandler(const std::string& path) const
        {
            return handlers_.find(path) != handlers_.end();
        }

        // Doesn't checks handler presence
        // May throw various exceptions
        std::string InvokeHandler(const std::string& path, const args_t& args) const
        {
            return handlers_.find(path)->second(args);
        }

    private:
        std::map<std::string, std::function<std::string(const args_t& args)>> handlers_;
    };

} } // namespaces


применение
Код

int foo(int x) { return x * 2; }
int bar(int x, int y) { return x + y; }

BOOST_AUTO_TEST_CASE(TestHandlers)
{
    UserHandlersWrapper handlers;
    handlers
        ("foo", foo, "x")
        ("bar", bar, "x", "y")
        ;

    std::map<std::string, std::string> args;
    args["x"] = "21";
    args["y"] = "4";

    BOOST_CHECK(handlers.InvokeHandler("foo", args) == "42");
    BOOST_CHECK(handlers.InvokeHandler("bar", args) == "25");
}

PM MAIL   Вверх
boostcoder
Дата 22.7.2010, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



этот код у вас работает?
тут:
Код

        template<typename Callable>
        this_t& operator()(const std::string& path, Callable [U]handler[/U])
        {
            handlers_[path] = [U][][/U](const args_t&) { return boost::lexical_cast<std::string>([U]handler[/U]()); };

в лямбда выражении, вы используете handler() по значению. но его не captured(не знаю как на русском сказать), квадратные скобки пусты.

Добавлено через 40 секунд
эм... теги в коде не работают smile

Добавлено через 10 минут и 11 секунд
да у вас в коде полно ошибок.
откуда код взят?
на каком компиляторе проверяли?

Добавлено через 13 минут и 8 секунд
в трех из четырех лямбда выражениях, вы выполняете capture по значению...зачем? они у вас и так, в аргументы методов передаются по значению.
PM WWW   Вверх
boostcoder
Дата 22.7.2010, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



собственно ответ тут: http://www.boost.org/doc/libs/1_43_0/libs/...troduction.html
PM WWW   Вверх
Abyx
Дата 22.7.2010, 22:11 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



boostcoder, в том коде ошибок нет. 
[] - это захват по умолчанию, по значению.
handler хватается по значению, т.к. он может быть локальной переменной вызывающей функции.
const char* nameN нет смысла передавать по ссылке


Цитата(boostcoder @  22.7.2010,  22:42 Найти цитируемый пост)
 http://www.boost.org/doc/libs/1_43_0/libs/...troduction.html 

действительно, там нет функторов о_О
странно %) всегда думал что они поддерживаются

PM MAIL   Вверх
boostcoder
Дата 22.7.2010, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(Abyx @  22.7.2010,  22:11 Найти цитируемый пост)
в том коде ошибок нет. 

 smile 

Цитата(Abyx @  22.7.2010,  22:11 Найти цитируемый пост)
[] - это захват по умолчанию, по значению.

мдя... может книжек почитать для начала? smile 

Цитата(Abyx @  22.7.2010,  22:11 Найти цитируемый пост)
handler хватается по значению, т.к. он может быть локальной переменной вызывающей функции.

это понятно. но зачем его еще и в лямбду передавать по значению?!
PM WWW   Вверх
Abyx
Дата 22.7.2010, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



boostcoder, действительно там ошибка, должно быть [=]

Цитата(boostcoder @  22.7.2010,  23:36 Найти цитируемый пост)
но зачем его еще и в лямбду передавать по значению?! 

а как еще его передавать в лямбду?
если передавать по ссылке, то после выхода из operator() эти ссылки будут указывать вникуда

Это сообщение отредактировал(а) Abyx - 22.7.2010, 23:25
PM MAIL   Вверх
boostcoder
Дата 22.7.2010, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(Abyx @  22.7.2010,  23:24 Найти цитируемый пост)
если передавать по ссылке, то после выхода из operator() эти ссылки будут указывать вникуда

ну как так?
ламбда выражение живет меньше чем блок кода тела метода. потому, ссылки будут актуальны все время жизни лямбда выражения.

Добавлено @ 23:36
а typename ваш компилятор не требует в подобных выражениях?
Код

typedef boost::function_types::parameter_types<Callable>::type params_t;


Это сообщение отредактировал(а) boostcoder - 22.7.2010, 23:46
PM WWW   Вверх
Abyx
Дата 22.7.2010, 23:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



Цитата(boostcoder @  23.7.2010,  00:35 Найти цитируемый пост)
ну как так?
ламбда выражение живет меньше чем блок кода тела функции. потому, ссылки будут актуальны все время жизни лямбда выражения.

вообще-то оно записывается в handlers_


Цитата(boostcoder @  23.7.2010,  00:35 Найти цитируемый пост)
а typename ваш компилятор не требует в подобных выражениях?

не требует, а зачем оно там?

(компилятор - msvc. gcc требует, ну и фиг с ним)

Это сообщение отредактировал(а) Abyx - 22.7.2010, 23:57
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0649 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.