2012-06-20 2 views
3

저는 VS, g ++, Clang으로 다음을 시도해 보았습니다. 그리고 운이나 왜곡 된 이유를 만들 수 없었습니다. 비동기를 바인딩하는 방법?

void foo() {} 

auto f = bind(async, foo); 

나는 오류가 비동기()을하지 않는 사람에 비해 발사 정책을 취하는 하나에 결합 할 수있는 혼란에서 줄기 의심 ... 아니면 내가 명시 적으로 (비동기를 제공해야) 해당 템플릿 유형 (예 : 비동기 < ...>)? 어느 쪽이든 위의 성명을 쓰는 적절한 방법은 무엇입니까?

편집 : 귀하의 제안들에 대한

감사합니다,하지만 (어떤 컴파일러) 다음 작품 없음은 :

bind(async<decltype(foo)>, foo); 

bind(async<void (*)()>, foo); 

bind(async<function<void()> >, foo); 
+4

예, 당신은 템플릿 인수를 전달해야합니다. 나는 람다 (lambda)를 사용하고 바인드 (bind)를 잊어 버린다. –

+1

아마도'async '를 시도해보십시오. –

답변

2

std::async은 템플릿 일뿐만 아니라 오버로드되었습니다. 원하는 템플리트뿐만 아니라 과부하도 선택해야합니다.

typedef decltype(&foo) foo_type; 
typedef std::result_of<foo_type()>::type foo_rettype; 

auto chosen_async= 
    static_cast<std::future<foo_rettype> (*)(foo_type &&)> 
    (&std::async<foo_type>); 

불행하게도, std::bind 바인딩 기능이를 rvalue 참조를 복용 허용하지 않는 것 같습니다. 따라서 std::bind(chosen_async, &foo)을 쓰는 것만으로는 효과가 없습니다. 이 문제에 대한 해결 방법은 Is there a reference_wrapper<> for rvalue references?에 설명되어 있습니다 :

template<typename T> struct adv { 
    T t; 
    explicit adv(T &&t):t(std::forward<T>(t)) {} 
    template<typename ...U> T &&operator()(U &&...) { 
    return std::forward<T>(t); 
    } 
}; 

template<typename T> adv<T> make_adv(T &&t) { 
    return adv<T>{std::forward<T>(t)}; 
} 

namespace std { 
    template<typename T> 
    struct is_bind_expression< adv<T> > : std::true_type {}; 
} 

우리는 한 가지 문제를 제외하고, std::bind(chosen_async, make_adv(std::move(&foo))) 말을 수행 할 것입니다 : 당신은 직접 우리의 래퍼 객체의 std::async 하나를 전달할 수 없습니다, 따라서 std::result_of<...> (따라서 std::bind). chosen_async이 반환 할 내용을 추론 할 수 없습니다. 그래서 우리는 명시 적으로 반환 형식 상태 :

auto async_bound= 
    std::bind<std::future<foo_rettype>>(chosen_async, 
             make_adv(std::forward<foo_type>(&foo))); 

이 모든 수행을 적어도 GCC 행복 할 수있을 정도로 충분한 것 같다 : http://ideone.com/gapLs. 물론


, 당신은 람다 식으로 자신에게 번거 로움의 톤을 절약 할 수있다 :

auto async_bound=[=]()->std::future<void> {return std::async(&foo);}; 
+0

이제 실행됩니다. 그것은 너무 추한 것입니다. 누군가 람다 표현식을 사용하도록 제안 했습니까? ;-) – Managu

+0

@Managu 조사에 힘든 일을 해 주셔서 감사합니다 (그리고 "템플릿 매개 변수를 제공하는 것"만큼 간단하지 않다는 것을 보여줍니다). 자, 진실을 말하면서, 나는 그 "문제"를 발견했을 때 다소 벗어났습니다. 나는 이것을위한 "현실 세계"의 필요성이 없다. 나는 auto f = bind (async, foo, _1)와 같은 것을 얻을 수 있는지 알아보기 위해 노력했다. f (11) .get(); f (22) .get(); 압축 된 버전입니다. 당신의 대답 후에, 나는 그것이 우아하게 행해질 수 있다고 확신하지 못합니다 ...하지만 여전히, 당신의 대답은 나중에 누군가에게 도움이 될 수 있습니다. 그 사람이 당신이나 나일 수도 있습니다. :) – screwnut

+0

@screwnut : 나는 많이 생각했다. 그리고 lambda는 여전히 더 좋습니다 :'auto fooasync = [=] (int i) -> decltype (async (& foo, i)) {return async (& foo, i);}' – Managu

2

당신은 async 템플릿 매개 변수를 제공해야합니다. 단지 하나가async에 바인딩되지 않습니다. 함수 템플리트의 각 인스턴스에 대해 하나씩 있습니다.

관련 문제