std :: is_same - сценарий использования унаследованных функций от integra_constant - PullRequest
1 голос
/ 26 мая 2019

Рассматривая реализацию std::is_same, мы видим несколько внутренних функций (унаследованных от integral_constant).Позвольте мне скопировать код g ++ для удобства:

  template<typename _Tp, _Tp __v>
  struct integral_constant {
      static constexpr _Tp                value = __v;
      typedef _Tp                         value_type;
      typedef integral_constant<_Tp, __v> type;
      constexpr operator value_type()   const noexcept { return value; }
      constexpr value_type operator()() const noexcept { return value; }
  };

  template<typename, typename>
  struct is_same : public integral_constant<bool, false> { };

  template<typename _Tp>
  struct is_same<_Tp, _Tp> : public integral_constant<bool, true> { };

Это дает нам несколько вариантов его использования:

  bool a1 = is_same<int, int>{};               // instantiate & then cast implicitly
  bool a2 = is_same<int, int>();               // instantiate & then cast implicitly
  bool a3 = is_same<int, int>::value;          // use static member
  bool a4 = is_same<int, int>{}();             // instantiate & then use operator() 
  bool a5 = is_same<int, int>{}.operator()();  // instantiate & then use operator()

Мне интересно, какие варианты использования существуют для этихдополнительные функции, и почему бы, например, короткая реализация, такая как

  template<class, class> constexpr bool is_same = false;
  template<class T> constexpr bool is_same<T,T> = true;

не достаточно?Тогда мы могли бы просто написать bool a = is_same<int,int> без {} или () или ::value.

Любые мысли приветствуются.

1 Ответ

3 голосов
/ 27 мая 2019

Ответ на этот вопрос в значительной степени исторический. Этот тип предшествует шаблонам переменных на десятилетие, поэтому предлагаемый вами вариант - анахронизм. Остальные были добавлены по частям для удобства использования.

<ч />

std::integral_constant был представлен еще в 2003 году, через N1424 . Так что это очень старая технология, технология C ++ 03. В то время это выглядело так:

template <class T, T v> 
struct integral_constant
{
   static  const T                value = v;
   typedef T                      value_type;
   typedef integral_constant<T,v> type;
};

Ни одна из дополнительных функций-членов, которые вы видите, и обратите внимание, что value также был просто static const, а не static constexpr. В конце концов, constexpr еще не было.

Много лет спустя, во время разработки C ++ 0x, была открыта проблема с библиотекой ( LWG1019 ), которая, учитывая новое добавление constexpr, расширила это до:

template <class T, T v>
struct integral_constant {
  static constexpr T value = v;
  typedef T value_type;
  typedef integral_constant<T,v> type;
  constexpr operator value_type() { return value; }
};

Эта проблема была решена N2976 .

Мотивация функции преобразования заключается в том, что она позволяет вам использовать объекты типа integral_constant в качестве этих значений. Для определенных стилей метапрограммирования, если у вас есть функция, которая возвращает, скажем, true_type напрямую, вы можете использовать ее сразу:

std::true_type foo();    
if (foo()) { ... }

Вместо того, чтобы писать if (foo().value) или что-то еще странное в этом роде. Однако для небулевых констант единственный способ получить значение при заданном объекте - это либо получить доступ к члену value, либо выполнить явное приведение (последний из которых требует, чтобы вы знали тип):

constant.value
static_cast<???>(constant)

, что привело к N3545 в 2013 году, добавив оператор вызова, позволяющий написать constant(), чтобы вернуть значение обратно. Это последнее дополнение действительно полезно? Я не знаю.

Примечательно, что все это предшествует шаблонам переменных - первая версия которых была N3615 . Опция, которую вы предлагаете иметь is_same просто в качестве шаблона переменной bool, не применялась до позднего времени. И даже с переменными шаблонами довольно удобно иметь разные типы, поэтому я не уверен, что мы пойдем по этому пути, даже если бы это было возможно. Трудно сказать в ретроспективе.

...