СФИНА Почему я не обнаруживаю подстрочный оператор std :: vector? - PullRequest
2 голосов
/ 21 июня 2019

Я написал какую-то бессмысленную метаданную шаблона, чтобы определить, существуют ли методы класса.

Структура шаблона has_subscript является специализированной, так что второй параметр шаблона равен void, если первый параметр шаблона имеет оператор индекса. Если найден подстрочный оператор, используется специализация, в противном случае SFINAE по умолчанию является неспециализированной версией.

У меня есть код, работающий с простой структурой foo (он настроен только для лучшего соответствия std::vector), но он неожиданно завершается с std::vector.

демонстрационная ссылка 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 ]

4 голосов
/ 21 июня 2019

Это связано с тем, как вы пытаетесь вывести operator[], оно работает для foo, но не для std::vector, потому что оно перегружено.

Выражение typename result_of<decltype(&T::operator[])(T,int)>::type нельзя использовать, поскольку &T::operator[] неоднозначно.

Если вы используете decltype(std::declval<T&>()[int()]), то он работает как положено (см. здесь ).

0 голосов
/ 21 июня 2019

Вы можете использовать std::is_detected из основы библиотеки 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

...