Как проверить, есть ли в классе оператор []? - PullRequest
3 голосов
/ 08 января 2020

Я пытаюсь проверить, не перегружен ли operator [] в каком-либо классе. Вот мой код:

template <class T, class = void>
struct has_operator : std::false_type {};

template <class T>
struct has_operator < T,
            std::void_t<decltype(std::declval<T>[](int i))>> :
            std::true_type {};

Но на самом деле он не работает.

Я пытаюсь писать как код, проверяющий код, если класс имеет operator ()

вот оно:

template <typename T,class=void>
struct callable_without_args: std::false_type{};

template <typename T>
struct callable_without_args<T
          ,std::void_t<decltype(std::declval<T>()())>>
  :std::true_type{};

Хорошо, этот код компилируется, но как сделать проверку именно в основном?:


template <class T, class = void>
struct has_operator : std::false_type {};

template <class T>
struct has_operator < T,
            std::void_t<decltype(std::declval<T>()[0])>> :
            std::true_type {};

Я сделал это!

#include <type_traits>
#include <tuple>
#include <vector>


template <class T, class = void>
struct has_operator : std::false_type {};

template <class T>
struct has_operator < T,
            std::void_t<decltype(std::declval<T>()[0])>> :
            std::true_type {};


struct T {
    int* arr;
    T(int a) {
        arr = new int[a];
    }
    const int& operator [] (int i) {
        return arr[i];
    }
};

int main() {
    bool test = has_operator<T>::value;

    test == true ? std::cout << "yes" : std::cout << "no";
}

1 Ответ

3 голосов
/ 08 января 2020

Не совсем ясно, что именно вы хотите, но ... следующее decltype() неверно

// ---------------------VVVVVVVVV   Wrong
decltype(std::declval<T>[](int i))

std::declval() - это (только объявленная) функция, которая не получает аргументы.

То есть: вы должны «позвонить», добавив «()» после «<T>».

Я полагаю, вы можете попробовать что-то вроде

// .....................VV  call std::declval   
decltype(std::declval<T>()[0])
// .......................^^^  and invoke operator [] over the retuned object

Это должно работать, когда operator[] класса T принимает целочисленное значение.

Если operator[] не принимает целочисленное значение (например: std::map с ключом, несовместимым с int), но если вам нужно значение другого типа, скажем, типа U, вы можете попробовать с другим std::declval()

// ........................VVVVVVVVVVVVVVVVV   U value
decltype(std::declval<T>()[std::declval<U>()])
...