2011-08-29 2 views
1

Visual Studio 2008 C++ 응용 프로그램에서 boost :: phoenix lambda 표현으로 단항 Functor를 대체하고 싶습니다.boost :: phoenix 배우로 단항 Functor 바꾸기

필자의 경우 문자열이 포함 된 개체 목록이 있습니다. 지정된 객체와 일치하지 않는 문자열을 가진 모든 객체를 제거하고 싶습니다. 그래서 저는 다음과 같은 알고리즘을 사용합니다 :

struct Foo 
{ 
    std::string my_type; 
}; 

struct NotMatchType 
{ 
    NotMatchType(const std::string& t) : t_(t) { }; 
    bool operator()(const Foo& f) const 
    { 
     return f.my_type.compare(t_) != 0; 
    }; 
    std::string t_; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::vector<Foo> list_of_foo; 

    /*populate with objects*/ 

    std::string some_type = "some type"; 

    list_of_foo.erase(
     std::remove_if(list_of_foo.begin(), 
         list_of_foo.end(), 
         NotMatchType(some_type)), 
     list_of_foo.end()); 

    return 0; 
} 

잘 작동합니다. 그러나,이 같은 간단한 람다 식으로 내 코드를 조금 정리하고 NotMatchType 펑 제거하기와 교체 싶습니다 분명히

using boost::phoenix::arg_names::arg1; 

list_of_foo.erase(
    std::remove_if(list_of_foo.begin(), 
        list_of_foo.end(), 
        arg1.my_type.compare(some_type) != 0), 
    list_of_foo.end()); 

,이 작동하지 않습니다.

나는 또한 시도 : (arg1->*&Foo::my_type).compare(some_type) != 0

무엇을 내가 부스트을하려면 어떻게해야합니까 : 피닉스 : 배우가 Foo 객체처럼?

답변

3

두 문자열 lhsrhs이 주어진 경우 lhs == rhs은 의미 상으로 lhs.compare(rhs) == 0과 동일하게 지정됩니다. 즉, 귀하의 functor가 수행하는 작업은 f.my_type != t_과 같습니다. 그와

마음에, 당신은 당신이로 피닉스와 함께 원하는 것을 표현할 수있다 : 공식적으로

bind(&Foo::my_type, arg1) =! ref(some_type) 

, 당신은 피닉스 배우에 회원 compare를 호출했다. 그 회원이 std::string에 속해 있기 때문에, 그것은 당신이 원하는 것이 아닙니다. 나는 일할 다음을 얻을 수 있습니다 :

typedef int (std::string::*compare_type)(std::string const&) const; 
compare_type compare = &std::string::compare; 
bind(compare, bind(&Foo::my_type, arg1), "") != 0; 

여기서 마지막 줄은 최종 펑터입니다. 하지만 표준 형식의 오버로드 된 멤버의 주소를 가져올 안정적인 방법이 없기 때문에 이는 좋지 않습니다. 즉, 위의 두 번째 줄은 컴파일되지 않을 수도 있습니다.

auto compare = [](std::string const& lhs, std::string const& rhs) 
{ return lhs.compare(rhs); }; 
// bind that functor and use it as a Phoenix actor etc 
+0

'arg1'은 포인터 타입을 나타내지 않으므로'operator -> * '를 사용하면 잘못되었습니다. '(& arg1) -> * & Foo :: my_type! = ref (some_type)'가 작동해야합니다. – ildjarn

+0

lambdas (C++ 11의 일부)는 비극적으로 Visual Studio 2008에서는 사용할 수 없습니다. – PaulH

+0

@ildjarn 따라 가지 않습니다. 'operator -> *'가 오버로드되었습니다; 필자가 보여준 코드가 제 편에 컴파일됩니다. –

4

직접 피닉스에서 std::string::compare() 꽤 못생긴 사용이 오버로드 된 이후, 우리는 그 주소를 취할 필요 : 오버로드 된 멤버를 호출 할 때 나중에 참조 할 수 있도록

나는 람다를 선호

phx::bind(
    static_cast<int (std::string::*)(std::string const&) const>(
     &std::string::compare 
    ), 
    phx::cref(some_type), 
    phx::bind(&Foo::my_type, arg1) 
) != 0 

을 그러나 Luc의 힌트를 따르고 단순히 객체 평등을 비교하면 더 쉽게 관리 할 수 ​​있습니다.

+0

boost :: bind를 사용하는 것과 다른 점은 무엇입니까? 'boost :: bind (& Foo :: my_type, _1)! = boost :: cref (some_type)'? 또한 'cref'를 사용하여 복사를하지 못하게해야합니까? – PaulH

+2

@PaulH : 예, boost :: bind는이 문맥에서 작동하지만'std :: bind'와'std :: tr1 :: bind'는 그렇지 않습니다. 네,'ref' 또는'cref'가 사용되지 않으면 복사본이 만들어집니다. – ildjarn

관련 문제