Предыдущее исследование в Могу ли я составить таблицу из String + лямбда-символов с одинаковой подписью? показал, что на самом деле я могу иметь таблицу строк-лямбда-выражений в VS2010.
Вещи выглядели хорошо, в то время как лямбды были пустого типа возврата.Но попытавшись изменить их на тип возвращаемого значения bool, компилятор, похоже, ошибся, или есть какая-то ошибка повреждения памяти ... что-то не так в земле C ++ ...
Следующее иллюстрируетСценарий:
// fun: use a table of lambdas to define what to do in order to update each field
typedef std::function<bool (CDynamicMenuItem *, ITEM *)> LambdaType;
struct UpdateField {
const TCHAR * label;
LambdaType lambda; // this version allows us to use captures in our lambdas, whereas the following doesn't
//void (*lambda)(CDynamicMenuItem *, ITEM *); // this would work in VS11, but the conversion of lambda to function pointer was defined after 2010's release!
};
UpdateField MenuFields[] = {
{ "Identity", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { return pMenuItem->SetText(FString("%s/%.1f", pNearestItem->thissec->name, pNearestItem->number/10.0)), true; } },
{ "X1", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetX1(pNearestItem); return (v != v) ? false : pMenuItem->SetValue(v), true; } },
{ "Y1", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetY1(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "X2", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetX2(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "Y2", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetY2(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "Xd", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetXd(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "Yd", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetYd(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "Angle", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetAngle(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "Length", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetLength(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
};
for (UpdateField * it = &MenuFields[0], * end = (MenuFields + countof(MenuFields)); it != end; ++it)
{
CDynamicMenuItem * pMenuItem = pMenu->FindItem(it->label);
if (pMenuItem)
{
if (!m_pNearestItem || !it->lambda(pMenuItem, m_pNearestItem))
pMenuItem->SetText("");
}
}
Вышеописанное прекрасно работало, когда лямбда-тип возврата пуст (т.е. -> bool опущен, а различные лямбда-тела изменены, чтобы ничего не возвращать и т. д.).
Тем не менее, мне полезно, чтобы они возвращали логическое значение, указывающее, была ли лямбда в состоянии обработать данные для этого поля, и если нет, чтобы обработчик вызовов очищал это поле.
конечно, код компилируется и запускается ... пока не попадет в этот код и не ударится.Глядя на «MenuFields []» в отладчике, можно увидеть мусор для большинства адресов MenuField [x] .label (иногда один из них правильный, но я не выяснил, что это за шаблон).
Я подумал, что, возможно, компилятор не справился с синтаксисом лямбды, встроенной в список статической инициализации, но я не уверен, что я могу с этим поделать?
Я попробовал этот вариант:
{ "Identity", LambdaType( [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { return pMenuItem->SetText(FString("%s/%.1f", pNearestItem->thissec->name, pNearestItem->number/10.0)), true; } ) },
Компилятору это нравится одинаково хорошо, но это приводит к тем же поврежденным данным таблицы.
Аналогично, установка круглых скобок вокруг всей лямбды является приемлемой для компилятора и одинаково повреждена во время выполнения.
Итак, несколько вопросов:
- Видите ли вы что-то, что я упустил?
- Можете ли вы придумать, как компилятору сгенерировать правильный код (кроме возврата назад)аннулировать возврат - что является вероятным для моего сценария, и мой вероятный следующий шаг, за исключением лучшего предложения)?
- Знаете, как лучше всего сообщить об этом в Microsoft?[Мне не повезло найти реальных людей на другом конце, чтобы дать такую подробную информацию, чтобы она действительно шла куда-то, кроме> nul)