在VS2010中使用lambda函数作为函数指针时遇到问题

时间:2015-11-05 15:22:35

标签: c++ visual-studio-2010 c++11 lambda

我正在尝试创建以下类,我可以使用它来测试对象,看看它们是否通过了一些过滤器。

template <typename T>
class Filter
{
public:
  typedef bool (*Functor)(const T&);

  bool test(const T& t) {
    return func(t);
  }

  void setTester(Functor f) {
    func = f;
  }

private:
  Functor func;
};

如果我只是在全局命名空间中创建一个方法,这可以正常工作。

bool testFunc(const Object& obj)
{
  return !obj.name().isEmpty();
}

void foo(const Object& obj)
{
  Filter<Object> filter;
  filter.setTester(testFunc);
  filter.test(obj);
}

但我真正喜欢的是使用lambda函数,这样我就不必像这样创建所有的过滤方法了。我希望能够即时创建它们。

void foo(const Object& object)
{
  Filter<Object> filter;

  filter.setTester([](const Object& object) {
    return !object.name().isEmpty();
  });

  filter.test(object);
}

但是当我这样做时,我得到以下编译错误。

C2664: 'ov::Filter<T>::setTester' : cannot convert parameter 1 from 'ov::`anonymous-namespace'::<lambda0>' to 'bool (__cdecl *)(const T &)'
with
[
    T=ov::Object
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

我已经阅读过关于将lambda函数作为函数指针传递的其他帖子,例如this one,我知道他们无法捕获它们才能使其工作。那没关系,你可以看到我不想捕捉任何东西。

我正在使用VS2010编译我的代码。

那么我做错了什么?

3 个答案:

答案 0 :(得分:1)

这对我来说很好,但假设类Object实际上是在某处定义的,成员名称()返回一个字符串,在这种情况下我使用public void setRunMode() { // _solution_path, _solution_name must be replaced by your solution path and solution name Type t = System.Type.GetTypeFromProgID("VisualStudio.DTE.10.0"); EnvDTE80.DTE2 dte2 = (EnvDTE80.DTE2)System.Activator.CreateInstance(t); dte2.MainWindow.Visible = false; //keep TwinCAT window closed Solution4 solution4 = (Solution4)dte2.Solution; EnvDTE.Project project = null; solution4.Open(Path.Combine(_solution_path, _solution_name + ".sln").ToString()); project = (EnvDTE.Project)solution4.Projects.Item(1); ITcSysManager5 sysmanager5 = (ITcSysManager5)project.Object; sysmanager5.StartRestartTwinCAT(); dte2.Quit(); } 而不是public void setRunMode() { TcAdsClient client = new TcAdsClient(); StateInfo mode = new StateInfo(); client.Connect((int)AmsPort.SystemService); mode.AdsState = client.ReadState().AdsState; mode.AdsState = AdsState.Reset; client.WriteControl(mode); client.Dispose(); }

我成功测试了以下代码:

empty()

输出:1

p.s:我正在使用VS2015。

答案 1 :(得分:1)

您的编译器可能不支持此功能。你正在使用MS,所以很多这些东西都会丢失。他们在最近的那些中获得了最重要的东西,但是回过头来一点也没多少。我不认为他们现在支持这个。

答案 2 :(得分:1)

如果明确设置输出类型会发生什么?

filter.setTester([](const Object& object) -> bool {
  return !object.name().isEmpty();
});