2017-03-15 19 views
2

최근에 C++ 17 표준에 도입 될 std::is_invocable을 우연히 발견했습니다. 사용자에게 왜 형식을 제공해야하는지 궁금합니다. 특히 비 형식 템플릿 매개 변수가 이제 제약을받지 않기 때문에 더욱 편리 할 수있는 함수 포인터 자체를 제공하는 것과는 대조적으로.std :: is_invocable이 non type 템플릿 매개 변수를 사용하지 않는 이유는 무엇입니까?

std::is_invocable에 대한

void hello_world() { 
    cout << "Hello world" << endl; 
} 
int main() { 
    cout << std::is_invocable_v<decltype(hello_world)> << endl; 
    // as opposed to being able to do 
    // cout << std::is_invocable_v<hello_world> << endl; 

    return 0; 
} 
+0

함수 포인터를 템플릿 매개 변수로 전달하면 닭 대 계란 문제가 발생할 수 있으므로 http://stackoverflow.com/questions/1174169/function-passed-as-template-argument(이 것을 느끼지 마십시오.)를 참조하십시오. 실제로 속는 사람입니다.) 함수의 유형을 첫 x 째 템플리트 매개 변수로 정의해야하지만 나머지 템플리트 매개 변수가 필요합니다. –

+0

하나는 유형이고 다른 하나는 값입니다. –

+1

@SamVarshavchik 야, 무슨 소리 야? C++ 17,'template auto'. – Barry

답변

4

궁금 오전 : 바로 지금, 당신은 같은 callF 기능을 사용할 수 있습니다 당신은 항상이 유형 테스트 할 것을 호출의을 가지고 있지만 때문에 편리

당신은 항상 const를로의 이없는 개미 식. 물론 foo 대신 decltype(foo) 대신에 쓸만한 가치가 있지만 상당히 부담스러운 것처럼 보일뿐 아니라 유스 케이스의 상당 부분을 차지할 것입니다. template <auto F, class... Args> is_invocable을 추가하는 것만으로도 가치가 있다고 확신 할 수는 없습니다. 가끔은 사용자가 decltype을 쓸 필요가 없습니다.

3

주 사용 아래의 예에서 설명 될 수있다 내 말 유형 및 템플릿 매개 변수와 함께 사용하는 것입니다. 함수 포인터를 직접 사용하는 것만으로는 사용할 수 없습니다.

은의 유용한 경우 코드 약간 수정 및 추가하자

void callF(F function, Args&& args) { 
    std::invoke(function, std::forward<Args>(args)...); 
} 

// Later, in your main 

callF(hello_world); 

당신은 호출의 호출이 무효 될 때 호출 될하지 않는 함수를 필터링하고 싶습니다. 당신은 그렇게 std::is_invokable를 사용할 수 있습니다 std::is_invocable에 인수로 전송

auto callF(F function, Args&& args) -> std::enable_if<std::is_invocable_v<F, Args...>> { 
    std::invoke(function, std::forward<Args>(args)...); 
} 

당신이 볼 수 있듯이, 유형이 std::invoke에 보낸 인수를 반영합니다.

보너스로, 훨씬 더 많은 함수 포인터가 지원됩니다. 함수 객체와 심지어 멤버 함수 포인터도 지원됩니다. 그것은 사용자가 필요한 이유 단지 더 할 수있는 함수 포인터 자체를 제공하기 위해 반대 함수 포인터에 대한 유형을 제공하기 위해

callF([](int i){ /* ... */ }, 8); 

struct Test { void test() {} }; 

Test t; 

callF(&Test::test, t);