【问题标题】:Trouble using lambda function as function pointer in VS2010 [closed]在VS2010中使用lambda函数作为函数指针时遇到问题[关闭]
【发布时间】:2016-02-06 12:21:08
【问题描述】:

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

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 编译我的代码。

那我做错了什么?

【问题讨论】:

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


【解决方案1】:

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

【讨论】:

  • 将 lambda 转换为函数指针至少在某些版本的 MSVC 编译器中有效...我认为 2015 年预发布的编译器中可能存在错误,但即使这样也应该使用隐式转换。
  • 你是对的。我正在使用 VS 2010。如果我尝试在 VS 2015 中构建它,那么它编译得很好。
【解决方案2】:

这对我来说很好,但前提是 Object 类实际上是在某处定义的,成员 name() 返回一个字符串,在这种情况下,我使用 empty() 而不是 isEmpty()

我成功测试了以下代码:

// class Filter: no modification
class Object { public:string name() const { return "name"; } };

bool foo(const Object& obj)
{ Filter<Object> filter;
  filter.setTester([](const Object& obj) { return !obj.name().empty();});
  return filter.test(obj);
}
int main()
{ Object c; cout << foo(c); 
  system("pause");
}

输出:1

ps:我使用的是 VS2015。

【讨论】:

  • 这似乎是一个编译器问题。当我切换到 VS2015 时,它编译得很好,但我目前正在使用 VS2010,所以我猜它不支持。
  • @Moohasha 这很有可能。 AFAIK VS2010 与 C++11 不完全兼容,并且有一些补丁要安装,所以这不足为奇。
【解决方案3】:

如果显式设置输出类型会怎样?

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

【讨论】:

  • 嘿,我认为这可能是问题所在;除了,! 不应该返回bool吗?
  • ! 仅在应用它的对象不重载时才返回bool。在这种情况下,编译器必须推断,对于您传递给函数的每个object,其方法name() 返回的对象的方法isEmpty() 不会使运算符重载。很难理解,不是吗?
  • 不,编译器只需要检查播放中的特定类型。该 lambda 的返回值为std::decay_t&lt; decltype( !std::declval&lt;Object const&amp;&gt;().name().isEmpty() ) &gt;。一旦确定,那就是固定的。然后它被传递给setTester,并且应该找到转换为函数的重载。如果使用实际类型,这将无法工作,!blah 不完全是bool。但是如果name()CString(看起来是这样),isEmpty() 返回BOOL! 将转换为bool
  • 我们没有Object 的代码...所以我们无法说出很多关于name() 的信息。请 OP 向我们提供有关该课程的详细信息。
猜你喜欢
  • 1970-01-01
  • 2012-07-15
  • 2015-01-24
  • 1970-01-01
  • 2015-01-07
  • 2017-09-19
  • 1970-01-01
  • 2018-08-24
  • 2014-04-24
相关资源
最近更新 更多