c++ - 如何改进此模板以在 VS2012 中接受 lambda

标签 c++ templates boost visual-studio-2012

以下是我经常使用的可爱小模板。简单地告诉我给定元素是否是集合的成员(集合本身必须与 find_if 模板兼容):

// returns true if a given collection contains the given element
// NOTE: This is NOT optimized for associative containers!
template <typename ELEMENT, typename COLLECTION, typename PREDICATE>
bool contains(const COLLECTION & collection, ELEMENT element, PREDICATE predicate)
{
    return collection.end() != std::find_if(collection.begin(), collection.end(), boost::bind(predicate, element, _1));
}

我发现如果我尝试使用 lambda 作为谓词,VC2012 会犹豫:

if (!contains(specs, str, [] (CString pathname, CString pattern) { return AsBool(PathMatchSpec(pathname, pattern)); }))
    continue;

VS2012SP1 针对上述上下文吐出以下内容:

1>c:\users\steve\projects\cimex cad-cam\15.0\3rd party\boost\boost\bind\bind.hpp(69): error C2039: 'result_type' : is not a member of 'CMacroInterpreter::GetDirectoryOf::<lambda_60eac39ee69a5bdc77e08d06d79ae4c4>'
1>          c:\users\steve\projects\cimex cad-cam\15.0\cimex application\cimcad\macro directory.cpp(166) : see declaration of 'CMacroInterpreter::GetDirectoryOf::<lambda_60eac39ee69a5bdc77e08d06d79ae4c4>'
1>          c:\users\steve\projects\cimex cad-cam\15.0\3rd party\boost\boost\bind\bind_template.hpp(15) : see reference to class template instantiation 'boost::_bi::result_traits<R,F>' being compiled
1>          with
1>          [
1>              R=boost::_bi::unspecified,
1>              F=CMacroInterpreter::GetDirectoryOf::<lambda_60eac39ee69a5bdc77e08d06d79ae4c4>
1>          ]
1>          c:\users\steve\projects\cimex cad-cam\15.0\mfc toolbox\miscellaneous.h(360) : see reference to class template instantiation 'boost::_bi::bind_t<R,F,L>' being compiled
1>          with
1>          [
1>              R=boost::_bi::unspecified,
1>              F=CMacroInterpreter::GetDirectoryOf::<lambda_60eac39ee69a5bdc77e08d06d79ae4c4>,
1>              L=boost::_bi::list2<boost::_bi::value<CString>,boost::arg<1>>
1>          ]
1>          c:\users\steve\projects\cimex cad-cam\15.0\cimex application\cimcad\macro directory.cpp(166) : see reference to function template instantiation 'bool contains<CString,substring_container_adapter,CMacroInterpreter::GetDirectoryOf::<lambda_60eac39ee69a5bdc77e08d06d79ae4c4>>(const COLLECTION &,ELEMENT,PREDICATE)' being compiled
1>          with
1>          [
1>              COLLECTION=substring_container_adapter,
1>              ELEMENT=CString,
1>              PREDICATE=CMacroInterpreter::GetDirectoryOf::<lambda_60eac39ee69a5bdc77e08d06d79ae4c4>
1>          ]

我不清楚如何强制事物接受谓词 lambda。似乎 boost 无法推断出 lambda 的返回类型。我不清楚我能做些什么来解决这个问题?

我可以定义一个本地 std::binary_function 导数仿函数。似乎修复 contains<> 以允许它直接处理 lambda 会更好。

最佳答案

这似乎是 boost::bind 的问题。使用 std::bind 代替,您的代码在 VS2012 中使用 lambda 构建得很好:

#include <functional>
#include <algorithm>
#include <vector>

template <typename ELEMENT, typename COLLECTION, typename PREDICATE>
bool contains(const COLLECTION & collection, ELEMENT element, PREDICATE predicate)
{
    return collection.end() != std::find_if(collection.begin(), collection.end(), std::bind(predicate, element, std::placeholders::_1));
}

std::vector<int> a;

int main()
{
    a.push_back(1);
    a.push_back(2);
    a.push_back(3);
    a.push_back(42);
    bool c = contains(a, 42, [](int a, int b) { return a == b; });
    return 0;
}

同样的代码也可以用 g++ 构建得很好。

关于c++ - 如何改进此模板以在 VS2012 中接受 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14408212/

相关文章:

c++ - 如何在 C++ 中将 HWND 转换为 LPCSTR

c++ - 在 C++ 中声明一点

c++模板成员函数,根据模板参数更改参数

templates - 如何在Grails 3.x中创建可重用的布局和脚手架模板

c++ - 转发引用错误时终端进程终止

c++ - 使用 std::string 键从 boost::unordered::unordered_map 恢复值时出错

c++ - constexpr 优先于 const

c# - C# 和 C++ 中字符串操作的不同基准

c++ - 将函数从结构传递给函数

c++ - boost日志的使用,Valgrind检查内存泄漏