8

Based on answers here and here I am trying to use the following

template <typename T>
using operator_square_brackets = decltype(&T::operator[]);

It fails on visual studio with

error C2760: syntax error: expected ')' not ']'

Any ideas on how to fix this?

sergej
  • 17,147
  • 6
  • 52
  • 89
Cookie
  • 12,004
  • 13
  • 54
  • 83

1 Answers1

8

If you want to detect whether a type has a certain function or overloaded operator you have to call that function or operator. This is important because you might have several overloads of a function or operator and overload resolution always depends on the caller.

Here is a small example, based on CppCon 2014: Walter E. Brown "Modern Template Metaprogramming: A Compendium, Part II" on how to detect operator[] in a type.

I have no idea why VC is giving you such a weird error which looks more like a parsing error. I would have expected something like »reference to overloaded function could not be resolved; did you mean to call it?«.

#include <string>
#include <type_traits>
#include <vector>

// in C++17 std::void_t
template < typename... >
using void_t = void;


template < typename T, typename Index >
using subscript_t = decltype(std::declval<T>()[std::declval<Index>()]);

template < typename, typename Index = size_t, typename = void_t<> >
struct has_subscript : std::false_type {};

template < typename T, typename Index >
struct has_subscript< T, Index, void_t< subscript_t<T,Index> > > : std::true_type {};


struct A
{
  void operator[](size_t) {}
};

struct B {};

int main ()
{
  static_assert(has_subscript< std::vector<int> >::value    == true , "!");
  static_assert(has_subscript< std::vector<double> >::value == true , "!");
  static_assert(has_subscript< A >::value                   == true , "!");
  static_assert(has_subscript< A, std::string >::value      == false, "!");
  static_assert(has_subscript< B >::value                   == false, "!");
  static_assert(has_subscript< double[5] >::value           == true , "!");
  static_assert(has_subscript< double* >::value             == true , "!");
  static_assert(has_subscript< double >::value              == false, "!");
}
Henri Menke
  • 10,705
  • 1
  • 24
  • 42
  • 6
    [is_detected](https://stackoverflow.com/documentation/c%2b%2b/1169/sfinae-substitution-failure-is-not-an-error/18585/is-detected#t=201707210748041399684) may interest you to generalize the concept. – Jarod42 Jul 21 '17 at 07:49
  • 3
    `std::map` would be a good example for an `Index` which is not `size_t`. – Jarod42 Jul 21 '17 at 07:52
  • If you don't use the error message parameter of `static_assert`, you can just omit it. – Rakete1111 Jul 21 '17 at 08:31
  • @Rakete1111 Not prior to c++17. – Holt Jul 21 '17 at 08:48
  • I'm trying to use this, while it checks for the operator overload, it does not specialize for subscript type, will return true every time. – joaocandre Nov 14 '18 at 01:35
  • @joaocandre Yes, you might be interested in this question then: https://stackoverflow.com/questions/45249985/how-to-require-an-exact-function-signature-in-the-detection-idiom – Henri Menke Nov 14 '18 at 01:49
  • @HenriMenke I'm tied to c++11 atm, so that solution won't do. Still, was just finding it curious why your example explicit defines `typename Index` and seems to not use it. I'm not sure if I'm doing something wrong, – joaocandre Nov 15 '18 at 15:55