2017-11-29 5 views
1

今はSFINAEを習得しようとしていますが、強制的に問題があるようですが、std::uint16_tに対応していないので、hasRead<Y>hasRead<Z>をどうすれば失敗するのですか? ?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はありません)を検出する機能を提供します。あなたが知識をひけらかすことには、それを同じよう

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

†を使用

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 {}; 

SFINAE in partial specializations is ill-formed in C++11 due to wording defects

+0

私は、私がもっと簡潔にできるいくつかの研究でこのような解決策を打ち出しました:https://godbolt.org/g/BTzufc – uknys

+0

素晴らしい!非常にシンプルでエレガントです。 – max66

0

私は(2)のタイプがuint8_t(T::*)(uint16_t)であるあなたは(1)関数が存在することを確認し、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

関連する問題