Re[8]: std::function, could not deduce template argument
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.15 04:09
Оценка: 23 (2) +1
Здравствуйте, c-smile, Вы писали:

CS>Это вот

CS>
CS>auto a = [](auto x){ cout << x << endl; }; 
CS>


CS>вообще-то не должно компилироваться вообще так как есть фактически это вот


CS>
CS>template <typename X> lambda_type [](X x){ cout << x << endl; };

CS>lambda_type<int> a; 
CS>a(1);

CS>lambda_type<double> a; 
CS>a(3.14);

CS>lambda_type<const char*> a; 
CS>a("asd");
CS>


CS>Но это смысла не имеет так как у тебя три переменные с одним именем.


CS>Или я чего-то не понял концептуально?


ага. у тебя template<class X> не там, он должен быть внутри, а не снаружи. Эквивалентный функциональный объект выглядит как-то так:
// template<class X> -- не здесь!
struct PrintX
{
  template<class X> // вот он где!
  void operator()(X x) { cout << x << endl; }; 
};

Если бы он был снаружи — твои соображения были бы верны.

ЗЫ Именно так работала и Boost.Lambda. Ты мог одно и то же имя (как а выше) вызывать с разными аргументами.
Добро пожаловать в С++14! (если ты пропустил вечеринку с Boost.Lambda)
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: std::function, could not deduce template argument
От: andyp  
Дата: 12.02.15 22:45
Оценка: 44 (1)
Если можешь прожить без auto, то так

int main(int argc, char* argv[]) { 
    std::function<void(int)> func1 = [](int x) { std::cout << x << std::endl; }; 
    std::function<void(int,int)> func2 = [](int x, int y) { std::cout << x << y << std::endl; }; 
    f(func1); 
    f(func2); 
    return 0; 
}
Re[9]: std::function, could not deduce template argument
От: PM  
Дата: 15.02.15 12:19
Оценка: 44 (1)
Здравствуйте, c-smile, Вы писали:

PM>>Еще по теме, а обязательно нужно стирание типов с std::function? Может быть удастся обойтись шаблонной f()


[здесь было объяснение]

А, это видимо реализация xcall в Sciter. Тогда да, тут нужно стирание типов. Как уже написал выше Булат, std::function и лямбды имеют разный тип. Так что нужно нечто, преобразующее лямбду в std::function, и без поддержки variadic templates придется писать набор перегруженных функций для разумного кол-ва аргументов, тут без вариантов.

Идея в том, чтобы в function_traits для лямбды хранить тип соответствующей std::function. Вот специализации function_traits для лямбд с 0..2 аргументами:

template<typename Function>
struct function_traits : public function_traits<decltype(&Function::operator())>
{
};

// []() -> R
template<typename Lambda, typename R>
struct function_traits<R(Lambda::*)() const>
{
    typedef std::function<R()> function;
};

// []() mutable -> R
template<typename Lambda, typename R>
struct function_traits<R(Lambda::*)()>
{
    typedef std::function<R()> function;
};

// [](P0) -> R
template<typename Lambda, typename R, typename P0>
struct function_traits<R(Lambda::*)(P0) const>
{
    typedef std::function<R(P0)> function;
};

// [](P0) mutable -> R
template<typename Lambda, typename R, typename P0>
struct function_traits<R(Lambda::*)(P0)>
{
    typedef std::function<R(P0)> function;
};

// [](P0, P1) -> R
template<typename Lambda, typename R, typename P0, typename P1>
struct function_traits<R(Lambda::*)(P0, P1) const>
{
    typedef std::function<R(P0, P1)> function;
};

// [](P0, P1) mutable -> R
template<typename Lambda, typename R, typename P0, typename P1>
struct function_traits<R(Lambda::*)(P0, P1)>
{
    typedef std::function<R(P0, P1)> function;
};

template <typename Function>
struct function_traits<Function&> :function_traits<Function>{};

template <typename Function>
struct function_traits<Function&&> :function_traits<Function>{};

template<typename Lambda> //TODO: enable_if Lambda::operator() ?
value vfunc(Lambda&& lambda)
{
    typedef typename function_traits<Lambda>::function function;
    return vfunc(static_cast<function>(lambda));
}


Полный код: http://coliru.stacked-crooked.com/a/861aea7b8ee370fb

Идея найдена здесь: http://meh.schizofreni.co/programming/magic/2013/01/23/function-pointer-from-lambda.html, вот еще тема на StackOverflow: http://stackoverflow.com/questions/13358672/how-to-convert-a-lambda-to-an-stdfunction-using-templates
Re[10]: std::function, could not deduce template argument
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.15 10:55
Оценка: 18 (1)
Здравствуйте, BulatZiganshin, Вы писали:

BZ>Здравствуйте, jazzer, Вы писали:


J>>>>В std::function<void(int)> var = []{} ты просишь компилятор проверить, можно ли использовать int (который ты своими руками написал).

J>>>>А исходная задача — вывести этот int.

J>>про то, как это может быть в конструкторе, я уже писал тут
Автор: jazzer
Дата: 16.02.15
.


BZ>я не вижу здесь никакой разницы с шаблонным вызовом функции. ты не мог бы привести этот конструктор?


ну типа так (пишу в браузере):
template<class F> // F - это void(int)
struct function
{
  F f;
  using argT = traits<F>....;  // int

                               //       объект-лямбда   объект-аргумент типа argT
  template<class L, class = decltype( ( *(L*)nullptr )( *(argT*)nullptr ) )> // SFINAE
  function(L lambda): f{lambda} {}

  //... другие конструкторы
};

этот конструктор скомпилируется, только если вызов lambda с аргументом типа argT валиден.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[12]: std::function, could not deduce template argument
От: Evgeny.Panasyuk Россия  
Дата: 16.02.15 11:35
Оценка: 12 (1)
Здравствуйте, BulatZiganshin, Вы писали:

J>> // объект-лямбда объект-аргумент типа argT

J>> template<class L, class = decltype( ( *(L*)nullptr )( *(argT*)nullptr ) )> // SFINAE
BZ>так SFINAE точно так же к вызовам функций применимо, в чём разница?

Разница в том, что здесь используется argT, пришедший через аргумент шаблона function.
Если в обычный шаблон функции также передавать дополнительный шаблонный параметр с типом сигнатуры, то будет работать и там.
Re[10]: std::function, could not deduce template argument
От: andyp  
Дата: 16.02.15 11:08
Оценка: 10 (1)
static_cast здесь не нужен.
return vfunc(static_cast<function>(lambda));

У std::function есть шаблонный конструктор из объекта-функтора, у которого есть operator().
Наверное, имелось в виду
return vfunc(function(lambda));
std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 12.02.15 20:16
Оценка: 3 (1)
Есть вот такая конструкция

#include <functional>
#include <iostream>

template <typename T>
void f(std::function<void(T)> g)
{
    std::cout << "1 arg:";
    g(1);
}

template <typename T1, typename T2>
void f(std::function<void(T1 t1,T2 t2)> g)
{
    std::cout << "2 args:";
    g(1,2);
}

int main(int argc, char* argv[])
{
    auto func1 = [](int x) { std::cout << x << std::endl; };
    auto func2 = [](int x, int y) { std::cout << x << y << std::endl; };

    f(func1);
    f(func2);

    return 0;
}


Попытка скомпилировать дает

error C2784: 'void f(std::function<void(T)>)' : could not deduce template argument for 'std::function<void(T)>' from 'main::<lambda_015bd0dc27990c8871eddd8030a68e56>' d:\tests\functional.cpp

Как бы исхитриться?

Ну или получить количество параметров std::function wrapper и их типы. Знаю как это сделать с пом. variadic templates, но на руках VS 2010, там этого нет.
Re: std::function, could not deduce template argument
От: Константин Россия  
Дата: 14.02.15 19:18
Оценка: -1
Здравствуйте, c-smile, Вы писали:


CS>Есть вот такая конструкция


CS>
CS>template <typename T>
CS>void f(std::function<void(T)> g)

CS>template <typename T1, typename T2>
CS>void f(std::function<void(T1 t1,T2 t2)> g)

CS>int main(int argc, char* argv[])
CS>{
CS>    auto func1 = [](int x) { std::cout << x << std::endl; };
CS>    auto func2 = [](int x, int y) { std::cout << x << y << std::endl; };

CS>    f(func1);
CS>    f(func2);

CS>    return 0;
CS>}
CS>


Какая-то пессимизация на пустом месте. Вместо функторов которые ещё и отлично инлайнятся, всё гонится через тяжёлый std::function. Зачем???

template <G> void f1(G g) {...}
template <G> void f2(G g) {...}

auto func1 = [](int x) { std::cout << x << std::endl; };
auto func2 = [](int x, int y) { std::cout << x << y << std::endl; };
f1(func1);
f2(func2);
Re: std::function, could not deduce template argument
От: _NN_ www.nemerleweb.com
Дата: 12.02.15 20:47
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Как бы исхитриться?

CS>Ну или получить количество параметров std::function wrapper и их типы. Знаю как это сделать с пом. variadic templates, но на руках VS 2010, там этого нет.

Ну если есть решение на вариадках, то несложно нагенерировать специализации.

Вроде как decltype поддерживается в VS 2010.

Вот вариант решения https://github.com/kennytm/utils/blob/master/traits.hpp. Переписать несложно будет для 2010 если других проблем не появится .
Идея проста, специализируем по operator() .

function_traits<decltype(lambda)>::arity содержит количество аргументов.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 12.02.15 21:43
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Здравствуйте, c-smile, Вы писали:


CS>>Как бы исхитриться?

CS>>Ну или получить количество параметров std::function wrapper и их типы. Знаю как это сделать с пом. variadic templates, но на руках VS 2010, там этого нет.

_NN>Ну если есть решение на вариадках, то несложно нагенерировать специализации.


_NN>Вроде как decltype поддерживается в VS 2010.


А как decltype тут поможет?
Re[2]: std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 12.02.15 23:41
Оценка:
Здравствуйте, andyp, Вы писали:

A>Если можешь прожить без auto, то так


A>
A>int main(int argc, char* argv[]) { 
A>    std::function<void(int)> func1 = [](int x) { std::cout << x << std::endl; }; 
A>    std::function<void(int,int)> func2 = [](int x, int y) { std::cout << x << y << std::endl; }; 
A>    f(func1); 
A>    f(func2); 
A>    return 0; 
A>}
A>


В принципе это вариант, да.
Re: std::function, could not deduce template argument
От: jazzer Россия Skype: enerjazzer
Дата: 13.02.15 01:22
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Ну или получить количество параметров std::function wrapper и их типы. Знаю как это сделать с пом. variadic templates, но на руках VS 2010, там этого нет.


Под решением с вариадиками ты имеешь в виду вот это?
http://stackoverflow.com/a/7943765
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 13.02.15 02:27
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, c-smile, Вы писали:


CS>>Ну или получить количество параметров std::function wrapper и их типы. Знаю как это сделать с пом. variadic templates, но на руках VS 2010, там этого нет.


J>Под решением с вариадиками ты имеешь в виду вот это?

J>http://stackoverflow.com/a/7943765

Да, именно это.
Re[3]: std::function, could not deduce template argument
От: _NN_ www.nemerleweb.com
Дата: 13.02.15 06:22
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Да, именно это.


А в чем проблема сгенерировать необходимое количество специализаций вручную ?

//template <typename ClassType, typename ReturnType, typename... Args>
//struct function_traits<ReturnType(ClassType::*)(Args...) const>

template <typename ClassType, typename ReturnType, typename Arg1>
struct function_traits<ReturnType(ClassType::*)(Arg1) const> { static const unsigned arity = 1;... }

template <typename ClassType, typename ReturnType, typename Arg1, typename Arg2>
struct function_traits<ReturnType(ClassType::*)(Arg1, Arg2) const> { static const unsigned arity = 2; ... }

...
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 13.02.15 19:39
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>А в чем проблема сгенерировать необходимое количество специализаций вручную ?


Слышишь эхо комбинаторного взрыва? Нет? А он есть...

От 0 до 8-ми аргументов. Да по всем типам функций: member/free, const/non-const, throws/not-throws, volatile и не очень...
Re[5]: std::function, could not deduce template argument
От: _NN_ www.nemerleweb.com
Дата: 13.02.15 20:12
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Слышишь эхо комбинаторного взрыва? Нет? А он есть...

CS>От 0 до 8-ми аргументов. Да по всем типам функций: member/free, const/non-const, throws/not-throws, volatile и не очень...

И что с того ? Простой скрипт все нагенерирует.
Коль нет вариадиков, хоть так извратиться.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: std::function, could not deduce template argument
От: PM  
Дата: 13.02.15 20:23
Оценка:
Здравствуйте, c-smile, Вы писали:

_NN>>А в чем проблема сгенерировать необходимое количество специализаций вручную ?


CS>Слышишь эхо комбинаторного взрыва? Нет? А он есть...

CS>От 0 до 8-ми аргументов. Да по всем типам функций: member/free, const/non-const, throws/not-throws, volatile и не очень...

Можно нагенерировать код с помощью Boost.Preprocessor: https://github.com/pmed/v8pp/blob/7f758ffd0c1ae1c2032c7643899fc4ea098c47cf/v8pp/proto.hpp
Или отдельным внешним скриптом.

Хотя, если доступен Boost, в нем кажется есть похожее: http://www.boost.org/doc/libs/1_57_0/libs/function_types/doc/html/index.html
Re[6]: std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 13.02.15 22:05
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Здравствуйте, c-smile, Вы писали:


CS>>Слышишь эхо комбинаторного взрыва? Нет? А он есть...

CS>>От 0 до 8-ми аргументов. Да по всем типам функций: member/free, const/non-const, throws/not-throws, volatile и не очень...

_NN>И что с того ? Простой скрипт все нагенерирует.

_NN>Коль нет вариадиков, хоть так извратиться.

2**7 = 128 деклараций ... да ну нафиг.

Лучше уж люди руками напишут

function<int(int,int)> sum = [](int a, int b) { return a + b; };


вместо модного

auto sum = [](int a, int b) { return a + b; };
Re[6]: std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 13.02.15 22:18
Оценка:
Здравствуйте, PM, Вы писали:

PM>Хотя, если доступен Boost, в нем кажется есть похожее: http://www.boost.org/doc/libs/1_57_0/libs/function_types/doc/html/index.html


Это для одного из headers моего SDK, требовать еще наличия boost совсем не comme il faut ни разу.
Re[7]: std::function, could not deduce template argument
От: PM  
Дата: 14.02.15 06:58
Оценка:
Здравствуйте, c-smile, Вы писали:

PM>>Хотя, если доступен Boost, в нем кажется есть похожее: http://www.boost.org/doc/libs/1_57_0/libs/function_types/doc/html/index.html

CS>Это для одного из headers моего SDK, требовать еще наличия boost совсем не comme il faut ни разу.

Я бы отказался от поддержки старых компиляторов и требовал С++11

Еще по теме, а обязательно нужно стирание типов с std::function? Может быть удастся обойтись шаблонной f():

template<typename G>
void f(G g)
{
    ....
    g();
}


А если нужно больше аргументов, воспользоваться std::bind:
void g1(int);
void g2(int, int);

f(std::bind(&g1, 1));
f(std::bind(&g2, 1, 2));
Re[7]: std::function, could not deduce template argument
От: _NN_ www.nemerleweb.com
Дата: 14.02.15 07:08
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, _NN_, Вы писали:


_NN>>Здравствуйте, c-smile, Вы писали:


CS>>>Слышишь эхо комбинаторного взрыва? Нет? А он есть...

CS>>>От 0 до 8-ми аргументов. Да по всем типам функций: member/free, const/non-const, throws/not-throws, volatile и не очень...

_NN>>И что с того ? Простой скрипт все нагенерирует.

_NN>>Коль нет вариадиков, хоть так извратиться.

CS>2**7 = 128 деклараций ... да ну нафиг.

Скрипт то генерирует , не вручную же =)

CS>Лучше уж люди руками напишут


Ну все таки разница есть между лямбдой и std::function.
Да и auto хочется везде использовать как только привыкаешь к удобству
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: std::function, could not deduce template argument
От: BulatZiganshin  
Дата: 14.02.15 09:26
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>void f(std::function<void(T)> g)

CS> auto func1 = [](int x) { std::cout << x << std::endl; };
CS> f(func1);

такой код не будет работать ни в каком c++ даже без второго определения f, поскольку лямбда и std::function — разные типы, и автоматом привести к нужному типу сквозь темплейт не получится. во всяком случае в vc2013/gcc49

вот так работает:

void f(std::function<void(int)> g)
    f(func1);

может, можно соорудить конвертор? типа такого:

template <typename T>
std::function<T> cvt(T &x) {return x;}

    auto func1 = cvt([](int x) { std::cout << x << std::endl; });
Люди, я люблю вас! Будьте бдительны!!!
Отредактировано 14.02.2015 9:39 BulatZiganshin . Предыдущая версия . Еще …
Отредактировано 14.02.2015 9:28 BulatZiganshin . Предыдущая версия .
Отредактировано 14.02.2015 9:28 BulatZiganshin . Предыдущая версия .
Re[8]: std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 14.02.15 17:30
Оценка:
Здравствуйте, PM, Вы писали:

PM>Здравствуйте, c-smile, Вы писали:


PM>>>Хотя, если доступен Boost, в нем кажется есть похожее: http://www.boost.org/doc/libs/1_57_0/libs/function_types/doc/html/index.html

CS>>Это для одного из headers моего SDK, требовать еще наличия boost совсем не comme il faut ни разу.

PM>Я бы отказался от поддержки старых компиляторов и требовал С++11


Не могу пока.

PM>Еще по теме, а обязательно нужно стирание типов с std::function? Может быть удастся обойтись шаблонной f()


Есть такой тип (variant, discriminated union)

class value 
{
public:
  value( int i );
  value( double f );
  value( string s );
  value( std::function<value(unsigned int argc, const value* argv)> func ); // value-function 

  template<typename T> T get() const;
};


И есть набор vfunc определений — конвертируют std::function в value-function

   // 
   template<typename R,typename P0>
      inline value vfunc( std::function<R(P0)> func )
      {
        return value([func](unsigned int argc, const value* argv) -> value { 
          R r = func(argc >= 1? argv[0].get<P0>(): P0() ); 
          return value(r); }); 
      }
    template<typename R,typename P0,typename P1>
      inline value vfunc( std::function<R(P0,P1)> func )
      {
        return value([func](unsigned int argc, const value* argv) -> value { 
          R r = func(argc >= 1? argv[0].get<P0>(): P0(),
                     argc >= 2? argv[1].get<P1>(): P1() ); 
          return value(r); }); 
      }

    ...


Это работает в принципе.

Но не для лямбд. Это вот не компилируется:

value local_func = vfunc( []{ int a, int b } { return a + b; } );


А это вот работает:

std::function<int(int,int)> t = []{ int a, int b } { return a + b; };
value local_func = vfunc( t );
Отредактировано 14.02.2015 17:35 c-smile . Предыдущая версия .
Re[2]: std::function, could not deduce template argument
От: BulatZiganshin  
Дата: 15.02.15 04:03
Оценка:
Здравствуйте, Константин, Вы писали:

К>template <G> void f1(G g) {...}

К>template <G> void f2(G g) {...}

а если f1 и f2 должны быть перегрузками одной функции?
Люди, я люблю вас! Будьте бдительны!!!
Re[2]: std::function, could not deduce template argument
От: jazzer Россия Skype: enerjazzer
Дата: 15.02.15 08:03
Оценка:
Здравствуйте, Константин, Вы писали:

К>Здравствуйте, c-smile, Вы писали:


К>Какая-то пессимизация на пустом месте. Вместо функторов которые ещё и отлично инлайнятся, всё гонится через тяжёлый std::function. Зачем???


У c-smile там фреймворк с колбеками, так что, я думаю, это для хранения оных, и в этом смысле std::function подходит лучше всего.
(Еще лучше подошел бы Boost.Signal, но c-smile не хочет тащить буст, за исключением того, что уже попало в std)
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: std::function, could not deduce template argument
От: BulatZiganshin  
Дата: 15.02.15 15:58
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Есть вот такая конструкция


вот так заработало с gcc49, но не msvc2013:

  Скрытый текст
#include <functional>
#include <iostream>

template <typename T>
void f(std::function<void(T)> g)
{
    std::cout << "1 arg:";
    g(-1);
}

template <typename T>
void f(void g(T))
{
    std::cout << "1 arg:";
    g(1);
}

template <typename T1, typename T2>
void f(void g(T1,T2))
{
    std::cout << "2 args:";
    g(11,22);
}

template <typename T1, typename T2, typename T3>
void f(void g(T1,T2,T3))
{
    std::cout << "3 args:";
    g(111,222,333);
}

int main(int argc, char* argv[])
{
    auto func1 = [](int x) { std::cout << x << std::endl; };
    auto func2 = [](int x, int y) { std::cout << x << y << std::endl; };
    auto func3 = [](int x, int y, int z) { std::cout << x << y << z << std::endl; };

    f(+func1);
    f(+func2);
    f(+func3);

    return 0;
}

ключевые моменты — "+func1" и "void f(void g(T1,T2))" в дополнение к перегрузке по std::function. сообщение msvc об ошибке тоже достойно увековечения:
lambda_as_std_function2.cpp(27) : error C2593: 'operator +' is ambiguous
        could be 'built-in C++ operator+(void (__cdecl *)(int))'
        or       'built-in C++ operator+(void (__vectorcall *)(int))'
        while trying to match the argument list '(main::<lambda_c762786ee855352b046bdd0fba86f419>)'


по большому счёту, я знаю библиотеки которые принимают шаблонные лямбды на входе (включая std), значит решение есть. вот что я вижу в одной из них:

  Скрытый текст
использование:
    /**
     * Same as the other writeFunction, except that the template parameter is automatically detected
     * This only works if the data is either a native function pointer, or contains one operator() (this is the case for lambdas)
     */
    template<typename... TData>
    void writeFunction(TData&&... data) noexcept {
        static_assert(sizeof...(TData) >= 2, "You must pass at least a variable name and a value to writeFunction");
        typedef typename std::decay<typename std::tuple_element<sizeof...(TData) - 1,std::tuple<TData...>>::type>::type
            RealDataType;
        typedef typename FunctionTypeDetector<RealDataType>::type
            DetectedFunctionType;
        
        return writeFunction<DetectedFunctionType>(std::forward<TData>(data)...);
    }

определение:
    // this structure takes a pointer to a member function type and returns the base function type
    template<typename TType>
    struct RemoveMemberPointerFunction { typedef void type; };          // required because of a compiler bug

    // this structure takes any object and detects its function type
    template<typename TObjectType>
    struct FunctionTypeDetector { typedef typename RemoveMemberPointerFunction<decltype(&std::decay<TObjectType>::type::operator())>::type type; };


// this structure takes any object and detects its function type
template<typename TRetValue, typename... TParameters>
struct LuaContext::FunctionTypeDetector<TRetValue (TParameters...)>             { typedef TRetValue type(TParameters...); };
template<typename TObjectType>
struct LuaContext::FunctionTypeDetector<TObjectType*>                           { typedef typename FunctionTypeDetector<TObjectType>::type type; };

// this structure takes a pointer to a member function type and returns the base function type
template<typename TType, typename TRetValue, typename... TParameters>
struct LuaContext::RemoveMemberPointerFunction<TRetValue (TType::*)(TParameters...)>                    { typedef TRetValue type(TParameters...); };
template<typename TType, typename TRetValue, typename... TParameters>
struct LuaContext::RemoveMemberPointerFunction<TRetValue (TType::*)(TParameters...) const>              { typedef TRetValue type(TParameters...); };
template<typename TType, typename TRetValue, typename... TParameters>
struct LuaContext::RemoveMemberPointerFunction<TRetValue (TType::*)(TParameters...) volatile>           { typedef TRetValue type(TParameters...); };
template<typename TType, typename TRetValue, typename... TParameters>
struct LuaContext::RemoveMemberPointerFunction<TRetValue (TType::*)(TParameters...) const volatile>     { typedef TRetValue type(TParameters...); };
Люди, я люблю вас! Будьте бдительны!!!
Re[3]: std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 15.02.15 18:13
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Константин, Вы писали:


К>>Здравствуйте, c-smile, Вы писали:


К>>Какая-то пессимизация на пустом месте. Вместо функторов которые ещё и отлично инлайнятся, всё гонится через тяжёлый std::function. Зачем???


J>У c-smile там фреймворк с колбеками, так что, я думаю, это для хранения оных, и в этом смысле std::function подходит лучше всего.


Это для передачи native functions в script. Можно считать что это callbacks в каком-то роде.
Решение, кстати, для любого script integration может быть полезно.

Скажем в script (JavaScript, TIScript) я могу написать такое:

function getRecordset( params ) {
   var nrs = ...; // opening  recordset somehow
   function nextRecord() { gets next record from nrs }
   function prevRecord() { gets prev record from nrs }
   
   // returns public API of the recordset, hides nrs completely: 
   return {
     next: nextRecord, 
     prev: prevRecord
     ...
   };
}


И использование

var rs = getRecordset("shoppingCartData");

while(var record = rs.next()) {
  ...
}


getRecordset может быть native (С++) функция

value getRecordset() {
  std::shared_ptr<db::recordset> nrs = ....

  std::function<value()> nextRecord = [nrs]() -> value {
    ... return next record as key/value map
    ... or 'undefined' as value() 
  };
  std::function<value()> prevRecord = [nrs]() -> value { ...  };

  value r; 
  r.set_item("next", vfunc(nextRecord) );
  r.set_item("prev", vfunc(prevRecord) );
  return r;
}


Это вот выше уже и так работает. Просто хотелось еще и auto разрешить.

Вот интересно, C++ компилятор же как-то проверяет типы слева и справа здесь:
 std::function<...> var = ...lambda...;


т.е. им можно, а нам не нельзя ?
Re[4]: std::function, could not deduce template argument
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.15 00:28
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Вот интересно, C++ компилятор же как-то проверяет типы слева и справа здесь:

CS>
CS> std::function<...> var = ...lambda...;
CS>


CS>т.е. им можно, а нам не нельзя ?


Ну он же тут проверяет конкретные указанные тобой типы аргументов, а не выводит их.

В этом смысле достаточно SFINAE в конструкторе по decltype(lambda(int(),int())) — в смысле, проверить, что для этих типов код компилируется (заодно и шаблонные автолямбды так же накрываются — а у них ведь тип аргумента в принципе невозможно вывести).

(Правда, не уверен, что это именно так работает в вц2010, да и знать не хочу, если честно, я не палеонтолог в душе Вполне возможно, что они у себя тупо недокументированным интерфейсом пользуются)
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 16.02.15 01:10
Оценка:
Здравствуйте, jazzer, Вы писали:

J>В этом смысле достаточно SFINAE в конструкторе по decltype(lambda(int(),int())) — в смысле, проверить, что для этих типов код компилируется (заодно и шаблонные автолямбды так же накрываются — а у них ведь тип аргумента в принципе невозможно вывести).


Если lambda это некий уникальный тип то почему бы не сделать

decltype(lambda [](int,int)->int) -> std::function<int(int,int)>


ну или хотя бы

auto foo = [](int a,int b) { return a + b; };

decltype(foo)::function_type -> std::function<int(int,int)>


Компайлер ведь этой всей информацией обладает...
Re[6]: std::function, could not deduce template argument
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.15 02:57
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, jazzer, Вы писали:


J>>В этом смысле достаточно SFINAE в конструкторе по decltype(lambda(int(),int())) — в смысле, проверить, что для этих типов код компилируется (заодно и шаблонные автолямбды так же накрываются — а у них ведь тип аргумента в принципе невозможно вывести).


CS>Если lambda это некий уникальный тип то почему бы не сделать


CS>
CS>decltype(lambda [](int,int)->int) -> std::function<int(int,int)> 
CS>


CS>ну или хотя бы


CS>
CS>auto foo = [](int a,int b) { return a + b; };

CS>decltype(foo)::function_type -> std::function<int(int,int)> 
CS>


CS>Компайлер ведь этой всей информацией обладает...


это возможно только в самом тривиальном случае.
как насчет вот этого?
  auto a = [](auto x){ cout << x << endl; };
  a(1);
  a(3.14);
  a("asd");
  
  std::function<void(int)> fi{a}; 
  std::function<void(double)> fd{a}; 
  std::function<void(const char*)> fs{a}; 

  fi(1);
  fd(3.14);
  fs("asd");

Какой function_type должен быть у а?

как насчет вот этого?
  auto b = [](double x){ cout << x << endl; };
  std::function<void(int)> fb{b};
  fb(3.14); // напечатает 3
  
  auto c = [](int x){ cout << x << endl; };
  std::function<void(double)> fc{c};
  fc(3.14); // тоже напечатает 3


ты можешь спросить компилятор: "Можно ли привести лямбду к std::function конкретного типа?", но не спросить: "А дай мне все std::function, которые можно инициализировать из этой лямбды".
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[7]: std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 16.02.15 03:43
Оценка:
Здравствуйте, jazzer, Вы писали:

CS>>
CS>>auto foo = [](int a,int b) { return a + b; };

CS>>decltype(foo)::function_type -> std::function<int(int,int)> 
CS>>


CS>>Компайлер ведь этой всей информацией обладает...


J>это возможно только в самом тривиальном случае.

J>как насчет вот этого?
J>
J>  auto a = [](auto x){ cout << x << endl; };
J>  a(1);
J>  a(3.14);
J>  a("asd");
  
J>  std::function<void(int)> fi{a}; 
J>  std::function<void(double)> fd{a}; 
J>  std::function<void(const char*)> fs{a}; 

J>  fi(1);
J>  fd(3.14);
J>  fs("asd");
J>

J>Какой function_type должен быть у а?

Это вот
auto a = [](auto x){ cout << x << endl; };


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

template <typename X> lambda_type [](X x){ cout << x << endl; };

lambda_type<int> a; 
a(1);

lambda_type<double> a; 
a(3.14);

lambda_type<const char*> a; 
a("asd");


Но это смысла не имеет так как у тебя три переменные с одним именем.

Или я чего-то не понял концептуально?

J>как насчет вот этого?

J>
J>  auto b = [](double x){ cout << x << endl; };
J>  std::function<void(int)> fb{b};
J>  fb(3.14); // напечатает 3
  
J>  auto c = [](int x){ cout << x << endl; };
J>  std::function<void(double)> fc{c};
J>  fc(3.14); // тоже напечатает 3
J>


Это вообще мрак если честно. Я не понимаю зачем оно так сделано. Зачем эти дурацкие касты?
Re[9]: std::function, could not deduce template argument
От: c-smile Канада http://terrainformatica.com
Дата: 16.02.15 05:30
Оценка:
Здравствуйте, jazzer, Вы писали:


CS>>Или я чего-то не понял концептуально?


J>ага. у тебя template<class X> не там, он должен быть внутри, а не снаружи. Эквивалентный функциональный объект выглядит как-то так:

J>
J>// template<class X> -- не здесь!
J>struct PrintX
J>{
J>  template<class X> // вот он где!
J>  void operator()(X x) { cout << x << endl; }; 
J>};
J>

J>Если бы он был снаружи — твои соображения были бы верны.

Зашибись, но как это работает в случае capturing lambda:

void test() {
  intptr_t counter = 0;
  auto lambda = [&counter](auto x) { counter += x; return counter; };
  lambda(5);
  lambda(5.5);
  lambda("hello");
}


?

J>ЗЫ Именно так работала и Boost.Lambda. Ты мог одно и то же имя (как а выше) вызывать с разными аргументами.

J>Добро пожаловать в С++14! (если ты пропустил вечеринку с Boost.Lambda)

С++14 ... Тут за счастье полную поддержку С++11 поиметь хотя бы.
Добро пожаловать в мир practical programming
Re[10]: std::function, could not deduce template argument
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.15 06:02
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Зашибись, но как это работает в случае capturing lambda:


CS>
CS>void test() {
CS>  intptr_t counter = 0;
CS>  auto lambda = [&counter](auto x) { counter += x; return counter; };
CS>  lambda(5);
CS>  lambda(5.5);
CS>  lambda("hello");
CS>}
CS>


Точно так же:
struct Lambda
{
  intptr_t& counter;

  template<class X>
  intptr_t operator()(X x) { counter += x; return counter; }; 
};

Естественно, строчка lambda("hello"); не скомпилируется.

CS>С++14 ... Тут за счастье полную поддержку С++11 поиметь хотя бы.

CS>Добро пожаловать в мир practical programming

Да я тоже на С++98 на работе сижу, все никак не переедем
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: std::function, could not deduce template argument
От: BulatZiganshin  
Дата: 16.02.15 07:03
Оценка:
Здравствуйте, jazzer, Вы писали:

CS>> std::function<...> var = ...lambda...;


J>Ну он же тут проверяет конкретные указанные тобой типы аргументов, а не выводит их.


насколько я понимаю, тут срабатывает шаблонный конструктор, так что задача ровно та же самая
Люди, я люблю вас! Будьте бдительны!!!
Re[6]: std::function, could not deduce template argument
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.15 07:08
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>Здравствуйте, jazzer, Вы писали:

CS>>> std::function<...> var = ...lambda...;
J>>Ну он же тут проверяет конкретные указанные тобой типы аргументов, а не выводит их.

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


Нет, не та же.
В std::function<void(int)> var = []{} ты просишь компилятор проверить, можно ли использовать int (который ты своими руками написал).
А исходная задача — вывести этот int.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[11]: std::function, could not deduce template argument
От: PM  
Дата: 16.02.15 08:28
Оценка:
Здравствуйте, jazzer, Вы писали:

CS>>
CS>>void test() {
CS>>  intptr_t counter = 0;
CS>>  auto lambda = [&counter](auto x) { counter += x; return counter; };
CS>>  lambda(5);
CS>>  lambda(5.5);
CS>>  lambda("hello");
CS>>}
CS>>


J>Точно так же:

J>
J>struct Lambda
J>{
J>  intptr_t& counter;

J>  template<class X>
J>  intptr_t operator()(X x) { counter += x; return counter; }; 
J>};
J>

J>Естественно, строчка lambda("hello"); не скомпилируется.

Я думал это будет operator()(X) const, а неконстантная версия используется с mutable lambda

auto lambda1 = [](int x) mutable { return x; }
auto lambda2 = [](int x) { return x; }

// сгенерированный компилятором эквивалент
struct generated_lambda1
{
    int operator()(int x) const { return x; }
}

struct generated_lambda2
{
    int operator()(int x) { return x; }
}
Re[12]: std::function, could not deduce template argument
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.15 08:32
Оценка:
Здравствуйте, PM, Вы писали:

PM>Я думал это будет operator()(X) const, а неконстантная версия используется с mutable lambda


Да, конечно, просто в случае захвата по ссылке это рояли не играет.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[9]: std::function, could not deduce template argument
От: Evgeny.Panasyuk Россия  
Дата: 16.02.15 09:24
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>
CS>   // 
CS>   template<typename R,typename P0>
CS>      inline value vfunc( std::function<R(P0)> func )
CS>      {
CS>        return value([func](unsigned int argc, const value* argv) -> value { 
CS>          R r = func(argc >= 1? argv[0].get<P0>(): P0() ); 
CS>          return value(r); }); 
CS>      }
CS>


Здесь получается лишняя std::function, а достаточно одной, которая в value.
Re[6]: std::function, could not deduce template argument
От: Evgeny.Panasyuk Россия  
Дата: 16.02.15 09:25
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Если lambda это некий уникальный тип то почему бы не сделать


CS>
CS>decltype(lambda [](int,int)->int) -> std::function<int(int,int)> 
CS>


CS>ну или хотя бы


CS>
CS>auto foo = [](int a,int b) { return a + b; };

CS>decltype(foo)::function_type -> std::function<int(int,int)> 
CS>


CS>Компайлер ведь этой всей информацией обладает...



Такую метафункцию (принимающую тип лямбды и возвращающую соответствующий тип std::function) можно сделать вручную — как уже показали выше через decltype
Автор: uzhas
Дата: 11.05.13
(+ эмуляция variadic'ов на MSVC2010).
Но, как уже заметили, есть ограничение — это полиморфные лямбды (которых нет в MSVC2010) и функциональные объекты с шаблонным либо перегруженным operator().
Re[7]: std::function, could not deduce template argument
От: BulatZiganshin  
Дата: 16.02.15 10:11
Оценка:
Здравствуйте, jazzer, Вы писали:

J>В std::function<void(int)> var = []{} ты просишь компилятор проверить, можно ли использовать int (который ты своими руками написал).

J>А исходная задача — вывести этот int.

это если std::function встроен в компилятор. я предполагаю, что он написан в обычном заголовочном файле и эта строка обрабатывается шаблонным конструктором. иными словами, напиши эквивалентный std::function тип, чтобы он такое принимал
Люди, я люблю вас! Будьте бдительны!!!
Re[8]: std::function, could not deduce template argument
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.15 10:35
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>Здравствуйте, jazzer, Вы писали:


J>>В std::function<void(int)> var = []{} ты просишь компилятор проверить, можно ли использовать int (который ты своими руками написал).

J>>А исходная задача — вывести этот int.

BZ>это если std::function встроен в компилятор. я предполагаю, что он написан в обычном заголовочном файле и эта строка обрабатывается шаблонным конструктором. иными словами, напиши эквивалентный std::function тип, чтобы он такое принимал


про то, как это может быть в конструкторе, я уже писал тут
Автор: jazzer
Дата: 16.02.15
.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[9]: std::function, could not deduce template argument
От: BulatZiganshin  
Дата: 16.02.15 10:41
Оценка:
Здравствуйте, jazzer, Вы писали:

J>>>В std::function<void(int)> var = []{} ты просишь компилятор проверить, можно ли использовать int (который ты своими руками написал).

J>>>А исходная задача — вывести этот int.

J>про то, как это может быть в конструкторе, я уже писал тут
Автор: jazzer
Дата: 16.02.15
.


я не вижу здесь никакой разницы с шаблонным вызовом функции. ты не мог бы привести этот конструктор?
Люди, я люблю вас! Будьте бдительны!!!
Re[11]: std::function, could not deduce template argument
От: BulatZiganshin  
Дата: 16.02.15 11:29
Оценка:
Здравствуйте, jazzer, Вы писали:

J>ну типа так (пишу в браузере):


попробуй в https://ideone.com/

J> // объект-лямбда объект-аргумент типа argT

J> template<class L, class = decltype( ( *(L*)nullptr )( *(argT*)nullptr ) )> // SFINAE

так SFINAE точно так же к вызовам функций применимо, в чём разница?
Люди, я люблю вас! Будьте бдительны!!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.