2017-12-18 17 views
2

std::experimental::is_detected 및 유사한 검색 유틸리티의 첫 번째 인수로 어떤 종류의 템플릿을 사용할 수 있는지 알고 싶습니다.is_detected와 함께 어떤 종류의 템플릿을 사용할 수 있습니까?

아래 붙여 넣기는 is_detected의 구현이며 유형 T.foo()이라는 멤버 함수가 있는지 검색하는 데 사용하려고했습니다. 이 사용하는 일반적인 패턴이 존재하는 경우 우선, 멤버 함수 T::foo의 타입을 반환하는 타입 특성을 정의하는 것이다

template<class T> 
using member_foo_result_t = typename member_foo_result<T>::type; 

문제 : 다음

template<class T> 
struct member_foo_result 
{ 
    using type = decltype(std::declval<T>().foo()); 
}; 

그것은 속기 별명을 정의 약식 별칭이 is_detected과 호환되지 않는 것 같습니다.

여기 컴파일러 출력, 전체 프로그램의 : 런타임시 :

#include <utility> 
#include <type_traits> 
#include <iostream> 

// implementation of is_detected 
template<class...> 
using void_t = void; 

struct nonesuch 
{ 
    nonesuch() = delete; 
    ~nonesuch() = delete; 
    nonesuch(const nonesuch&) = delete; 
    void operator=(const nonesuch&) = delete; 
}; 


template<class Default, class AlwaysVoid, 
     template<class...> class Op, class... Args> 
struct detector 
{ 
    using value_t = std::false_type; 
    using type = Default; 
}; 


template<class Default, template<class...> class Op, class... Args> 
struct detector<Default, void_t<Op<Args...>>, Op, Args...> 
{ 
    using value_t = std::true_type; 
    using type = Op<Args...>; 
}; 
template<template<class...> class Op, class... Args> 
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t; 



// returns the result type of T::foo() 
template<class T> 
struct member_foo_result 
{ 
    using type = decltype(std::declval<T>().foo()); 
}; 

// shorthand alias for member_foo_result<T>::type 
template<class T> 
using member_foo_result_t = typename member_foo_result<T>::type; 


// detects whether or not the member function T::foo() exists 
template<class T> 
struct has_foo_member : is_detected<member_foo_result_t, T> {}; 


struct doesnt_have_foo_member {}; 


int main() 
{ 
    std::cout << "result: " << has_foo_member<doesnt_have_foo_member>::value << std::endl; 
} 

나는이 프로그램이 "0 결과를"인쇄 할 전망이다. 그러나 올바르게 컴파일되지 않습니다.

$ clang -std=c++11 test_is_detected.cpp 
test_is_detected.cpp:41:43: error: no member named 'foo' in 'doesnt_have_foo_member' 
    using type = decltype(std::declval<T>().foo()); 
         ~~~~~~~~~~~~~~~~~^
test_is_detected.cpp:45:1: note: in instantiation of template class 'member_foo_result<doesnt_have_foo_member>' requested here 
using member_foo_result_t = typename member_foo_result<T>::type; 
^ 
test_is_detected.cpp:27:33: note: in instantiation of template type alias 'member_foo_result_t' requested here 
struct detector<Default, void_t<Op<Args...>>, Op, Args...> 
           ^
test_is_detected.cpp:33:1: note: during template argument deduction for class template partial specialization 'detector<type-parameter-0-0, void, Op, type-parameter-0-2...>' [with Default = nonesuch, Op = 
     member_foo_result_t, Args = <doesnt_have_foo_member>] 
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t; 
^ 
test_is_detected.cpp:50:25: note: in instantiation of template type alias 'is_detected' requested here 
struct has_foo_member : is_detected<member_foo_result_t, T> {}; 
         ^
test_is_detected.cpp:58:30: note: in instantiation of template class 'has_foo_member<doesnt_have_foo_member>' requested here 
    std::cout << "result: " << has_foo_member<doesnt_have_foo_member>::value << std::endl; 
          ^
1 error generated. 

내가 잘못 사용하고 있습니까 is_detected?

답변

4

is_detected은 "잘못된"인수로 인스턴스화 할 때 즉각적인 컨텍스트 (즉, SFINAE 친화적 인)에서 오류를 유발하는 별칭 템플릿과 함께 사용해야합니다. 치환 실패 별명 템플릿 자체에서 발생하는 요구를 탐지 할 수 있음을 의미

오히려 어떤 클래스 템플릿과는 인스턴스화

template<class T> 
using member_foo_result_t = decltype(std::declval<T>().foo());