2016-07-23 36 views

回答

1

爲了完整起見,我想發佈之前未提到的另一種方法。
這是基於函數的定義和別名聲明。
它遵循最小的工作示例:

#include <vector> 
#include <type_traits> 
#include<utility> 

using namespace std; 

template<typename T, typename... U> 
constexpr auto f(int) 
-> std::conditional_t<false, decltype(std::declval<T>().push_back(std::declval<U>()...)), std::true_type>; 

template<typename, typename...> 
constexpr std::false_type f(char); 

template<typename T, typename... U> 
using has_push_back = decltype(f<T, U...>(0)); 

class MyColl : public vector<int> {}; 

int main() { 
    static_assert(has_push_back<vector<int>, int>::value, "!"); 
    static_assert(has_push_back<MyColl, int>::value, "!"); 
} 
1

this答案,你的代碼看起來是這樣的:

#include <type_traits> 

// Primary template with a static assertion 
// for a meaningful error message 
// if it ever gets instantiated. 
// We could leave it undefined if we didn't care. 

template<typename, typename T> 
struct has_push_back { 
    static_assert(
     std::integral_constant<T, false>::value, 
     "Second template parameter needs to be of function type."); 
}; 

// specialization that does the checking 

template<typename C, typename Ret, typename... Args> 
struct has_push_back<C, Ret(Args...)> { 
private: 
    template<typename T> 
    static constexpr auto check(T*) 
    -> typename 
     std::is_same< 
      decltype(std::declval<T>().push_back(std::declval<Args>()...)), 
      Ret // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
     >::type; // attempt to call it and see if the return type is correct 

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

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

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

所有學分@jork

你可能已經從this答案使用代碼,但它不具有繼承功能的工作。

template<typename... Ts> 
using void_t = void; 

template<typename T> 
using push_back_test = decltype(std::declval<T>().push_back(std::declval<typename T::const_reference>())); 

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

template<typename T> 
struct has_push_back<T, void_t<push_back_test<T>>> : std::is_same<push_back_test<T>, void> {}; 

或者:

2

a solution使用void_t,這是一個標準的C++ 17還配備了額外的工具,如is_detected_exact在圖書館基礎V2 TS,同時大部分的工作出has_push_back這裏的with future utilities

template<typename T> 
using push_back_test = decltype(std::declval<T>().push_back(std::declval<typename T::const_reference>())); 

template<typename T> 
using has_push_back = std::experimental::is_detected_exact<void, push_back_test, T>; 

如果您想了解詳細介紹一下void_t,我建議您查看Walter Brown's CppCon 2015 talks

2
template<typename Coll> 
struct has_push_back { 
    template< 
     typename T, 
     typename = decltype(
      std::declval<T&>().push_back(std::declval<typename T::value_type>()) 
     ) 
    > 
    static std::true_type Test(int); 

    template<typename T> 
    static std::false_type Test(long); 

    using type = decltype(Test<Coll>(0)); 
    static constexpr bool value = type::value; 
}; 

Online Demo

相關問題