c++ - How to check for the existence of a subscript operator? -
i want write type trait uses sfinae check type existence of subscript expression. initial attempt below seems work when subscript expression possible not work when bracket operator not exist.
#include <iostream> #include <vector> #include <cassert> template<class t, class index> struct has_subscript_operator_impl { template<class t1, class reference = decltype( (*std::declval<t*>())[std::declval<index>()] ), class = typename std::enable_if< !std::is_void<reference>::value >::type> static std::true_type test(int); template<class> static std::false_type test(...); using type = decltype(test<t>(0)); }; template<class t, class index> using has_subscript_operator = typename has_subscript_operator_impl<t,index>::type; struct doesnt_have_it {}; struct returns_void { void operator[](int) {} }; struct returns_int { int operator[](int) { return 0; } }; int main() { std::cout << "has_subscript_operator<doesnt_have_it,int>: " << has_subscript_operator<doesnt_have_it,int>::value << std::endl; assert((!has_subscript_operator<doesnt_have_it,int>::value)); std::cout << "has_subscript_operator<returns_void,int>: " << has_subscript_operator<returns_void,int>::value << std::endl; assert((!has_subscript_operator<returns_void,int>::value)); std::cout << "has_subscript_operator<returns_int,int>: " << has_subscript_operator<returns_int,int>::value << std::endl; assert((has_subscript_operator<returns_int,int>::value)); std::cout << "has_subscript_operator<int*,int>: " << has_subscript_operator<int*,int>::value << std::endl; assert((has_subscript_operator<int*,int>::value)); std::cout << "has_subscript_operator<std::vector<int>,int>: " << has_subscript_operator<std::vector<int>,int>::value << std::endl; assert((has_subscript_operator<returns_int,int>::value)); return 0; }
clang-3.4
's output:
$ clang -std=c++11 -i. -lstdc++ test_has_subscript_operator.cpp test_has_subscript_operator.cpp:10:14: error: type 'doesnt_have_it' not provide subscript operator (*std::declval<t*>())[std::declval<index>()] ^~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ test_has_subscript_operator.cpp:25:1: note: in instantiation of template class 'has_subscript_operator_impl<doesnt_have_it, int>' requested here using has_subscript_operator = typename has_subscript_operator_impl<t,index>::type; ^ test_has_subscript_operator.cpp:41:66: note: in instantiation of template type alias 'has_subscript_operator' requested here std::cout << "has_subscript_operator<doesnt_have_it,int>: " << has_subscript_operator<doesnt_have_it,int>::value << std::endl; ^ 1 error generated.
how can fix has_subscript_operator
such works correctly types?
sfinae works when substitution failure happens in immediate context. template parameter index
known time member function template test
being instantiated, instead of substitution failure hard error.
the trick working around deduce index
again adding additional template type parameter test
, default index
.
template<class t1, class indexdeduced = index, // <--- here class reference = decltype( (*std::declval<t*>())[std::declval<indexdeduced>()] // , use here ), class = typename std::enable_if< !std::is_void<reference>::value >::type> static std::true_type test(int);
now code works intended.
Comments
Post a Comment