SFINAE Why am I not detecting std::vector's subscript operator?

Viewed 121

I've written some template-meta nonsense to detect if class methods exists.

The template struct has_subscript is specialized so that the second template parameter is void if the first template parameter has a subscript operator. If the subscript operator is found, the specialization is used, otherwise SFINAE defaults to the non-specialized version.

I have the code working for a simple struct foo (it's templated just to better match std::vector), but it unexpectedly fails with std::vector.

demo link https://godbolt.org/z/5-QzAp

#include <type_traits>
#include <iostream>
#include <vector>
using namespace std;

template <typename>
struct void_wrap
{ using type = void; };


template <typename T, typename = void>
struct has_subscript
{
  static constexpr bool value = false;
};

template <typename T>
struct has_subscript <T, typename void_wrap<typename result_of<decltype(&T::operator[])(T,int)>::type>::type >
{
  static constexpr bool value = true;
};

template <typename T>
struct foo
{
  double operator[](size_t x){return 0.0;}
};

int main()
{
  cout << has_subscript<foo<int>>::value;
  cout << has_subscript<vector<int>>::value;
}
2 Answers

It has to do with how you are attempting to deduce the operator[], it works for foo but not for std::vector because it is overloaded.

The expression typename result_of<decltype(&T::operator[])(T,int)>::type cannot be used since &T::operator[] is ambiguous.

If you use decltype(std::declval<T&>()[int()]), then it works as expected (see here).

You can use std::is_detected from the library fundamentals TS v2.

#include <type_traits>
#include <experimental/type_traits>
#include <vector>

template<typename T>
using bracket_op_t = decltype( std::declval<T&>()[0] );

template<typename T>
constexpr bool has_bracket_op = std::experimental::is_detected<bracket_op_t, T>::value;

int main()
{
    // static_assert(has_bracket_op<int>, ""); // fails to compile
    static_assert(has_bracket_op<std::vector<int>>, "");
}

LIVE DEMO

Related