C ++ Как сделать так, чтобы шаблон & lt; T & gt; f () возвращал -1 для целого T, nullptr для типа указателя

Мне нужно сделать следующее:

template<typename T>
f() {
:
return { -1 if T is of integral type, else nullptr }
}

В моем конкретном случае использования T может быть одного из четырех типов:

int
Py_ssize_t  // ssize_t
Py_hash_t   // ssize_t

PyObject*   // PyObject is some C struct

Это лучшее решение, которое у меня есть:

template<typename T>
T test(typename enable_if<is_integral<T>::value, void*>::type = nullptr)
{ return -1; }

template<typename T>
T test(typename enable_if<is_pointer<T>::value, void*>::type = nullptr)
{ return nullptr; }

ideone

Но использует ли это кувалду, чтобы сломать орех?

Мое единственное возражение состоит в том, что это решает более широкую область проблемы, но я не уверен, завершено ли это без дополнительной работы с std :: decay.

У меня есть привычка сопротивляться искушению усложнить код, чтобы он мог также решить мнимые расширения рассматриваемой области проблемы.

Но в этом случае я не вижу более простого решения.

4

Решение

Это намного понятнее, если вы положите enable_if на тип возврата:

template <typename T>
typename std::enable_if<is_integral<T>::value, T>::type
test() {
return -1;
}

template <typename T>
typename std::enable_if<is_pointer<T>::value, T>::type
test() {
return nullptr;
}
2

Другие решения

Не думай об этом. Вы можете просто использовать:

template<typename T>
T f() { return std::is_integral<T>::value ? T(-1) : T(0); }

Это работает даже с T(-1) преобразование, если T является типом указателя, потому что это преобразование может быть неопределенным только во время выполнения, а не во время компиляции, но во время выполнения никогда не выполняется.

4

По запросу для данных типов это может быть упрощено до

template<typename T>
T f() { return -1; }

template<>
PyObject* f<PyObject*>() { return nullptr; }
3

template<class T>
T f2(std::true_type /* is integral */){return -1;}
template<class T>
T f2(std::false_type /* is integral */){return nullptr;}
template<class T>
T f(){ return f2(std::is_integral<T>{}); }

если есть сомнения, отправка метки.

Вы можете скрыть f2 в пространстве имен деталей.

Это избавляет от шума SFINAE.

Если вы хотите сбой SFINAE для плохих типов, вы можете сделать некоторые decltype и auto и связать их с f3 который проверяет тип указателя. Еще меньше спама.

3
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector