2017-11-29 13 views
1

지금은 SFINAE를 배우려고합니다.하지만 강요에 문제가있는 것 같습니다. hasRead<Y>hasRead<Z>은 메서드 인수가 std::uint16_t에 해당하지 않으므로 어떻게해야합니까? ?C++ SFINAE 및 숫자 변환 (강요)

내가 원하는대로 작동하도록하려면 어떻게해야할까요? 사전 :

#include <cstdint> 
#include <iostream> 
#include <utility> 

template<typename Class> 
struct hasRead { 
private: 
    template<typename T> 
    static constexpr auto check(T *) -> typename std::is_same< 
     decltype(std::declval<T>().read(std::declval<uint16_t>())), uint8_t>::type; 


    template<typename> 
    static constexpr std::false_type check(...); 

    typedef decltype(check<Class>(0)) type; 

public: 
    static constexpr bool value = type::value; 
}; 

struct X { 
    uint8_t read(uint16_t x) { return 3; } 
}; 

struct Y { 
    uint8_t read(uint8_t x) { return 3; } 
}; 

struct Z { 
    uint8_t read(int64_t x) { return 3; } 
}; 

static_assert(hasRead<X>, ""); 
static_assert(hasRead<Y>, ""); 
static_assert(hasRead<Z>, ""); 

답변

2

내가, 멤버 함수의 존재를 감지에 더 현대적인 접근 방식을 제공하는 detection idiom으로 알고 싶어 전체 컴파일 예에게 있습니다.

요약 된 버전에는 C++ 11이 필요합니다. . 더 간결하며 이렇게하면 템플릿 구성원 기능 (max66's version하지 않음)을 감지하는 기능을 제공합니다.

template<typename T, uint8_t (T::*)(uint16_t) = &T::read> 
using detectRead = void; 

template<typename, typename = void> 
struct hasRead : std::false_type {}; 

template<typename T> 
struct hasRead<T, detectRead<T>> : std::true_type {}; 

당신은 학자 연에 같은 방법

struct A { uint8_t read(uint16_t); }; 
struct B {}; 
struct C { uint8_t read(uint32_t); }; 
struct D 
{ 
    template<typename T, typename U> 
    U read(T); 
}; 

void test() 
{ 
    static_assert(hasRead<A>::value, ""); // OK 
    static_assert(hasRead<B>::value, ""); // fails 
    static_assert(hasRead<C>::value, ""); // fails 
    static_assert(hasRead<D>::value, ""); // OK 
} 

Live

†를 사용 SFINAE in partial specializations is ill-formed in C++11 due to wording defects

+0

나는 이런 연구를 통해 좀 더 간결해질 수있는 연구 결과를 얻었다. https://godbolt.org/g/BTzufc – uknys

+0

그레이트! 매우 간단하고 우아한. – max66

0

에서

덕분에 나는 당신이 존재하는 (1) 기능을 확인하고 uint16_t 및 그 (2)의 형태가 uint8_t(T::*)(uint16_t) 인을 받아 들일 수 있다고 생각.

뭔가

template <typename Class> 
struct hasRead 
{ 
    private: 
     template <typename T> 
     static constexpr auto check (T * t) 
     -> decltype(t->read(uint16_t{}), 
      std::is_same<decltype(&T::read), uint8_t(T::*)(uint16_t)>{}); 

     template<typename> 
     static constexpr std::false_type check(...); 

    public: 
     static constexpr bool value = decltype(check<Class>(nullptr))::value; 
}; 

처럼 다음은

#include <cstdint> 
#include <iostream> 
#include <utility> 

template <typename Class> 
struct hasRead 
{ 
    private: 
     template <typename T> 
     static constexpr auto check (T * t) 
     -> decltype(t->read(uint16_t{}), 
      std::is_same<decltype(&T::read), uint8_t(T::*)(uint16_t)>{}); 

     template<typename> 
     static constexpr std::false_type check(...); 

    public: 
     static constexpr bool value = decltype(check<Class>(nullptr))::value; 
}; 

struct X { uint8_t read(uint16_t x) { return 3; } }; 
struct Y { uint8_t read(uint8_t x) { return 3; } }; 
struct Z { uint8_t read(int64_t x) { return 3; } }; 
struct A { }; 

int main() 
{ 
    static_assert(true == hasRead<X>::value, ""); 
    static_assert(false == hasRead<Y>::value, ""); 
    static_assert(false == hasRead<Z>::value, ""); 
    static_assert(false == hasRead<A>::value, ""); 
} 
+0

의 사용량이 많은 완벽 덕분에 작품! – uknys