Странный оператор?: использование с decltype

#c #decltype

#c #decltype

Вопрос:

Я читаю книгу, в которой объясняются черты C , и есть пример из заголовка C type_traits со странным ?: использованием, вот цитата из соответствующего файла /usr/include/c /…:

 template<typename _Tp, typename _Up>
  static __success_type<typename decay<decltype
                        (true ? std::declval<_Tp>()
                         : std::declval<_Up>())>::type> _S_test(int);
  

Оставляя в стороне цель данного объявления, ?: использование оператора озадачивает меня в этом коде. Если первый операнд равен true , то std::declval<_Tp>() всегда будет выбираться в результате вычисления.
Как на самом деле работает этот выбор операнда declval?

Редактировать: первоначально прочитано в книге Николая М. Джосуттиса «Стандартная библиотека C : учебное пособие и справочник, 2-е изд.», стр.125. Но там он представлен в несколько упрощенной форме по сравнению с тем, что есть в моих файлах заголовков GCC.

Комментарии:

1. Кстати, что за книга?

2. Здесь важен тип выражения, а не то, какая часть будет вычисляться.

3. Что сказал Mat. Выражение используется для использования механизма вычета типов троичных условных операторов (вы можете прочитать их здесь ).

Ответ №1:

В выражении true ? std::declval<_Tp>() : std::declval<_Up>() всегда выбирается первая альтернатива, но все выражение должно быть допустимым выражением. So std::declval<_Up>() должно быть допустимым, и это означает _Up , что должен быть вызываемый объект, который принимает нулевые аргументы. Кроме того, _Tp() и _Up() должен возвращать тот же тип (или один из типов должен быть неявно преобразован в другой), иначе троичный итератор не сможет выбрать возвращаемое значение.

Этот метод называется SFINAE (ошибка замены не является ошибкой). Идея заключается в том, что если создание экземпляра шаблона завершается неудачно, то это не ошибка, и этот шаблон просто игнорируется, а компилятор ищет другой.

Комментарии:

1. Они не должны возвращать точно такой же тип, если доступна неявная последовательность преобразования.

Ответ №2:

Идея здесь в том, что ?: требуется, чтобы второй и третий операнды имели один и тот же тип, или один тип преобразуется в другой.

В противном случае создание экземпляра функции завершится неудачно, и будет выбрана какая-то другая перегрузка.