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.

live demo


Comments

Popular posts from this blog

python - No exponential form of the z-axis in matplotlib-3D-plots -

php - Best Light server (Linux + Web server + Database) for Raspberry Pi -

c# - "Newtonsoft.Json.JsonSerializationException unable to find constructor to use for types" error when deserializing class -