Неявная конверсия лямбды в указатель, msvc2013
От: johny5 Новая Зеландия
Дата: 09.06.15 23:12
Оценка:
Всем привет,

Есть ли трюк подобный этому:
auto ptr = +[](){};  //ptr is of type void (*)()


Но чтобы компилировалось в MSVC2013.
Там оно ругается на ambiguity, потому что MSVC предоставляет 4ре перегрузки, под каждый calling convention.

Может темплейтик какой написать, который мог бы принимать captureless лямбду и конвертировать её в указатель.
auto ptr = (ToPointer)[](){};
Re: VS bug: new int(1,2,"wtf")
От: Constructor  
Дата: 11.06.15 17:48
Оценка:
Здравствуйте, johny5, Вы писали:

J>Есть ли трюк подобный этому:

J>
J>auto ptr = +[](){};  //ptr is of type void (*)()
J>


J>Может темплейтик какой написать, который мог бы принимать captureless лямбду и конвертировать её в указатель.

J>
J>auto ptr = (ToPointer)[](){};
J>


Держите вот такой несложный трюк (компилируется на clang 3.6.0 и g++ 5.1.0 с -std=c++11 -Wall -Wextra -Werror -pedantic-errors и на Visual Studio 2015 RC, на Visual Studio 2013 RTM не компилируется, может быть повезет с более новыми версиями Visual Studio 2013 Update X):

#include <type_traits>

template <typename Type>
struct RemoveQualifier_
{
    using type = Type;
};

template <typename ReturnType, typename... Arguments>
struct RemoveQualifier_<ReturnType(Arguments...)const>
{
    using type = ReturnType(Arguments...);
};

template <typename Function>
using RemoveQualifier = typename RemoveQualifier_<Function>::type;

template <class C, typename F>
RemoveQualifier<F>* ExtractFunction(F C::*);

template <typename Lambda>
auto ToFunctionPointer(Lambda&& lambda) -> decltype(ExtractFunction(&Lambda::operator()))
{
    return lambda;
}


Использовать можно так:

auto function1 = ToFunctionPointer([](){ std::cout << "Usual lambda without a capture list." << std::endl; });    
auto function2 = ToFunctionPointer([](int i) mutable { std::cout << "Mutable lambda without a capture list. Parameter value: " << i << std::endl; });
    
function1();
function2(42);


Т.е. можно работать даже с мутабельными лямбдами (хотя без списка захвата они тождественны обычным, но их оператор operator() все же не имеет квалификатора const, поэтому нужно реализовывать общий вариант шаблона RemoveQualifier_, иначе можно было бы просто написать template <typename> struct RemoveQualifier_;).
Решение.
От: johny5 Новая Зеландия
Дата: 12.06.15 01:25
Оценка:
Здравствуйте, Constructor, Вы писали:

Поигрался с вашим примером.
Вот такое заработало на MSVC2013:

  auto lambda = [](int a){ std::cout << "Usual lambda without a capture list." << std::endl; };
  function_traits< decltype(&decltype(lambda)::operator()) >::function_type*  f = lambda;

  f(5);


function_traits отсюда:
https://functionalcpp.wordpress.com/2013/08/05/function-traits/

Я только добавил
  typedef R (function_type)( Args... ) ;

(почему то не получилось написать через using function_type = R (Args ...);

Осталось спрятать это всё под капот конвертера ToFunctionPointer.

Спасибо за помощь.
Отредактировано 12.06.2015 1:29 johny5 . Предыдущая версия . Еще …
Отредактировано 12.06.2015 1:28 johny5 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.