std :: add_pointer, для чего используется try_add_pointer в возможной реализации? - PullRequest
1 голос
/ 30 марта 2020

В cppreference add_pointer сказано, что мы можем реализовать его как:

namespace detail {

template <class T>
struct type_identity { using type = T; }; // or use std::type_identity (since C++20)

template <class T>
auto try_add_pointer(int) -> type_identity<typename std::remove_reference<T>::type*>;
template <class T>
auto try_add_pointer(...) -> type_identity<T>;

} // namespace detail

template <class T>
struct add_pointer : decltype(detail::try_add_pointer<T>(0)) {};

Мой вопрос: для чего нужен try_add_pointer? Я знаю, что это СФИНА. Но зачем реализация здесь?

Ответы [ 2 ]

4 голосов
/ 30 марта 2020

Если вы прочитаете на странице cppreference, вы заметите это предложение

В противном случае (если T является cv- или ref-квалифицированным типом функции), предоставляется тип typedef члена, который равен Тип T.

Функция имеет свои типы. Обычно в нормальном коде вы видите типы типа int(int), то есть тип функции, которая принимает одно целое число и возвращает целое число. Это тип аргумента, который std::function ожидает, например, std::function<int(int)>.

Однако набор типов функций также содержит странности, которые относятся к функциям-членам. Например,

struct foo {
  int bar(int) const;
};

int(int) const является типом функции bar. Хотя этот тип существует в системе типов, его использование ограничено.

[dcl.fct]

6 A cv-qualifier-seq или ref-qualifier должен входить только в:

  • тип функции для нештатной c функции-члена,
  • тип функции, для которой указатель на член ссылается,
  • на тип функции верхнего уровня объявления функции typedef или объявления псевдонима,
  • идентификатор типа в аргументе по умолчанию для параметра типа ([temp .param]), или
  • идентификатор типа аргумента шаблона для параметра типа ([temp.names]).

Эффект квалификатора cv -seq в деклараторе функции - это не то же самое, что добавить cv-квалификацию поверх типа функции. В последнем случае cv-квалификаторы игнорируются. [Примечание: тип функции, имеющий cv-qualifier-seq, не является cv-квалифицированным типом; не существует cv-квалифицированных типов функций. - конец примечания] [Пример:

typedef void F();
struct S {
  const F f;        // OK: equivalent to: void f();
};

- конец примера] Тип возвращаемого значения, список параметров-типов, квалификатор ref и cv-qualifier-seq, но не аргументы по умолчанию ( [dcl.fct.default]) или спецификация исключения ([exc.spec]), являются частью типа функции.

Таким образом, эта черта позволяет вам передавать ей тип функции, такой как int() const и ожидается, что он вернет его без изменений.

Вот тут и приходит try_add_pointer. Поскольку, как видно из приведенного выше списка, нет регулярных указателей на функции такого рода, мы получим замену ошибка в typename std::remove_reference<T>::type*. Но благодаря SFINAE существует запасной вариант.

2 голосов
/ 30 марта 2020

Обрабатывается ссылка"отвратительные типы функций"

std::add_pointer<int&>::type - int*. int&* недействительно.

std::add_pointer_t<int() const> является int () const

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...