1

以下は私がよく使うかわいい小さなテンプレートです。指定された要素がコレクションのメンバーであるかどうかを簡単に教えてくれます (それ自体が 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));
}

ラムダを述語として使用しようとすると、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>          ]

述語ラムダを受け入れるように強制する方法がわかりません。ブーストはラムダの戻り値の型を推測できないようです。そして、それを修正するために何ができるかわかりませんか?

ローカルの std::binary_function 派生ファンクターを定義できます。ラムダを直接処理できるように、contains<> を修正したほうがよいようです。

4

2 に答える 2

5

に問題があるようboost::bindです。代わりに使用std::bindすると、コードは VS2012 のラムダで正常にビルドされます。

#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++ます。

于 2013-01-18T22:01:14.020 に答える
2

いつでも別のラムダを使用してみることができます:

template <typename ELEMENT, typename COLLECTION, typename PREDICATE>
bool contains(const COLLECTION & collection, ELEMENT element, PREDICATE predicate)
{
    typedef typename COLLECTION::value_type VALUE;

    return collection.end() != std::find_if(collection.begin(), collection.end(),
      [&]( VALUE const & e ){ return predicate( element, e ); });
}
于 2013-01-18T22:05:50.933 に答える