2

Есть, например, класс. Вот его заголовок

ref class MyClass
{
    public:
    void Execute();
    property Action^ Act;
}

Как мне из функции main задать для этого Act безымянную функцию? Хочу чтобы было как то так

int main(array<System::String ^> ^args)
{
    auto mc = gcnew MyClass();
    mc->Act = [](){};
}

Получаю в этом случае ошибку, типа не верные аргументы для MyClass::Act::set

Оно и понятно, надо создавать новый Action. Делаю так

int main(array<System::String ^> ^args)
{
    auto mc = gcnew MyClass();
    mc->Act = gcnew Action(nullptr, [](){});
}

Понимаю, что чего то тут не так написано... ну и соответственно ошибка "Недопустимый инициализатор делегата -- требуется функция".

Думаю, из примеров понятно, чего я хочу. Подскажите, как это осуществить.

αλεχολυτ
  • 28,987
  • 13
  • 60
  • 119
iRumba
  • 5,946

1 Answers1

3

C++/CLI умеет "делегаты", C++0x умеет "лямбды". Они не совместимы. Можно нагородить костыли http://www.codeproject.com/Articles/277612/Using-lambdas-Cplusplus-vs-Csharp-vs-Cplusplus-CX

class LambdaRunner
{
  function<int(int)> _lambda;

public:
  LambdaRunner(function<int(int)> lambda) : _lambda(lambda)
  {
  } 

  int Run(int n)
  {
      return _lambda(n);
  }
};

ref class RefLambdaRunner
{
  LambdaRunner* pLambdaRunner;

  int Run(int n)
  {
    return pLambdaRunner->Run(n);
  }

public:
  RefLambdaRunner(function<int(int)> lambda)
  {
    pLambdaRunner = new LambdaRunner(lambda);
  }

  Func<int, int>^ ToDelegate()
  {
    return gcnew Func<int, int>(this, &RefLambdaRunner::Run);
  }

  void Close()
  {
    delete pLambdaRunner;
  }
};

Юзать так

auto lambda = [](int x) -> int { return x * 2; };
auto lambdaRunner = gcnew RefLambdaRunner(lambda);
int result  = lambdaRunner->ToDelegate()(10);
lambdaRunner->Close();

Короче C++/CLI не умеет нормальный C++, полная печаль.

VIP
  • 608
  • что нужно подключить, чтобы использовать это function<int(int)>? – iRumba Dec 09 '15 at 11:04
  • http://en.cppreference.com/w/cpp/utility/functional/function – VIP Dec 09 '15 at 11:58
  • Да, я это нашел, но у меня нет класса std::function. Я не знаю почему. – iRumba Dec 09 '15 at 12:01
  • 1
    Хедер functional заинклудили? – VIP Dec 09 '15 at 12:13
  • Ну все вроде заинклудил, копирую класс LambdaRunner, а он выдает кучу ошибок синтаксических на этапе компиляции. Причем не подчеркивает ничего. Ошибки, типа пропущены точки с запятой... Ничего не пропущено, ошибки левые какие то. Как отлавливать их, не представляю (( – iRumba Dec 09 '15 at 12:32
  • На чистом проекте такая лажа? Может где то еще что то влияет что не в этом коде? – VIP Dec 09 '15 at 12:36
  • Поигрался с инклудами, все прошло )). Теперь другая беда. В примере используется функция, которая принимает 1 параметр int и возвращает int (function<int(int)>), а мне надо процедуру без параметров. function<void(void)> не канает :( – iRumba Dec 10 '15 at 04:16
  • нашел. function<void()>. Однако все равно чего то не работает. Когда создаю объект RefLambdaRunner, студия подсказывает, что в списке его параметров не function<void()>, а . Ну и компилятор не жрет лямбду, которую я отправляю в конструктор. В чем дело, не понимаю ((( – iRumba Dec 10 '15 at 04:26
  • Причем, если я напишу так std::function<void()> f = []() { };, то все норм отрабатывает – iRumba Dec 10 '15 at 04:37
  • Шикарно! Все получилось! Кроме самого важного. Я не могу передать в лямбду экземпляр управляемого класса. То есть не могу написать так [TheMyRefObject]() {};, а без этого нет смысла в этом лямбда ранере ( – iRumba Dec 10 '15 at 05:44