2013-07-19 2 views
23

Visual Studio 2013 Preview는 (this 페이지에 따라) "Transparent Operator Functors"라고하는 C++ 14 기능을 지원합니다. 그게 무슨 뜻인지는 분명하지 않습니다. 내가 찾은 가장 가까운 C++ 14 제안은 이것입니다. 그러나 똑같은지 확실하지 않습니다. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421투명한 연산자 Functors

나는 그것이 무엇인지, 왜 개선인지, 그리고 왜 더 좋은지에 대한 이유를 찾고 있습니다. 어쩌면 그 사용법을 보여줄 수 있습니다.

+0

동일하면 bool less를 :: operator() (int const & lhs, int const & rhs)로 대체 할 수 있습니다. const {return lhs (lhs) (rhs)) {return std :: forward }}}}}}}}}}}}}}}}이 함수는 다음과 같이 정의된다. (lhs) (rhs); }'완벽한 전달 "투명"호출을'<'. – Yakk

+4

N3421은 동일합니다.이 회의에서 수정하지 않고 C++ 14에 투표했으며, 2013 년 미리보기에서 구현했습니다. Section II, "Motivation and Scope"에서 문제와 해결책을 명확히 설명 할 수있을 것으로 생각했으며, 제 8 장 "구현"의 예가 그 사용법을 입증했다고 생각했습니다. 너 혼란스러워? –

+0

"Visual C++의 새로운 기능"페이지에는 N3421 제안이 언급되어 있지 않으므로 여기에서 묻습니다. 나는 지금 그것에 분명하다. 추가 해줘서 고마워. – GravityWell

답변

22

투명한 연산자 functor 제안은 <functional>에있는 일반화 된 펑터를 갖는 방법입니다. 저는 개인적으로 제안 자체가 그 필요성을 설명하는 데 도움이 될 아주 좋은 본보기라고 생각합니다. 그러나 나는 앞으로 나아가 그것을 설명하려고 노력할 것이다. 당신이 <algorithm> 헤더에이 일반화 기능을 사용하려면 그러나

template<typename T, typename U> 
auto less_than(T&& t, U&& u) -> decltype(std::forward<T>(t) < std::forward<U>(u)) { 
    return std::forward<T>(t) < std::forward<U>(u); 
} 

:

는 함수, 아주 기본적인 기능의 마음을 가지고 가정하자.

struct MyLessThanFunctor { 
    template<typename T, typename U> 
    auto operator()(T&& t, U&& u) -> decltype(std::forward<T>(t) < std::forward<U>(u)){ 
     return std::forward<T>(t) < std::forward<U>(u); 
    } 
}; 

또는에서 C++ (14), 다형성 람다 수 있도록 :과 같이 알고리즘에서 사용되는 경우

[](auto&& t, auto&& u) -> decltype(auto) { 
    return std::forward<decltype(t)>(t) < std::forward<decltype(u)>(u); 
} 

모두 매우 장황를 당신은 그것을 구조체 펑터를 만들기 위해, 두 가지 옵션이 있습니다 :

을 :

int main() { 
    std::vector<int> v = {112,12,1281271,1919101,29181,412,1 }; 
    std::sort(std::begin(v), std::end(v), MyLessThanFunctor()); // one 
    std::sort(std::begin(v), std::end(v), [](auto&& t, auto&& u) -> decltype(auto) { 
     return std::forward<decltype(t)>(t) < std::forward<decltype(u)>(u); 
    }); 
} 

이 제안은 더 작고 대신을 수행하여 일반화 수 있도록하는 것을 목표로210

이것은 완벽한 전달을 제공하며 절단이나 컨테이너 변경으로 인해 발생하는 문제는 해결하지만 용지에서 언급 한 컨테이너가 지정한 기본 유형은 문제를 해결합니다.

당신이 아닌 일반 펑 있다고 가정하자 :

struct Functor { 
    bool operator()(uint32_t a, uint32_t b) { 
     return a < b; 
    } 
}; 

을 그리고 당신은 당신의 std::vector<uint32_t> 함께 사용하고는 모두 잘 작동하지만 당신은 일반화되지 않는 당신의 펑 잊고 당신의 std::vector<uint64_t>와 함께 사용. 발생한 문제를 볼 수 있습니까? 요소는 비교되기 전에 잘릴 것입니다. 아마도 사용자가 원하지 않았을 것입니다. 일반화 된 펑터는 발생하기 전에이 문제를 해결합니다.

+2

'std :: less' 등을 사용할 수 있습니다. 심지어 이러한 투명한 펑터가 구현되지 않아도, 훨씬 더 불투명합니다.'std :: sort (std :: begin (v), std :: end (v), std :: less :: type>()), ' – Praetorian

+9

Praetorian은 C++ 11의 이기종 lower_bound()를 고려해보십시오. 범위와 원하는 값은 서로 다른 유형을 가질 수 있습니다. C++ 98의 값이 보다 작 으면 const (const T &, const T &)를 사용하므로 어떤 T를 선택하든 이종 비교를 수행 할 수 없습니다. 이것은 std :: string 및 const char *와 같은 간단한 경우에도 중요합니다. –

+0

동등한 람다는'[] (자동 && t, 자동 && u) -> decltype (자동) {반환 std :: forward (t) (u); }', 슬프게도 –