Тип времени удержания - PullRequest
       4

Тип времени удержания

0 голосов
/ 06 февраля 2019

Я столкнулся с этой проблемой ранее сегодня.В следующем коде:

template <int> struct Holder {};

template <typename> struct Helper { using T = Holder<__COUNTER__>; };  // ???

int main() {
  auto a = typename Helper<bool>::T();
  auto b = typename Helper<int>::T();

  std::cout << (typeid(a) == typeid(b)) << std::endl;
  return 0;
}

При компиляции и выполнении с:

g++ test.cpp -std=c++11 -o test
./test

Он печатает 1 вместо 0, что означает, что 2 Ts в Helper<int> и Helper<bool>одного типа, что заставляет меня задуматься:

  1. Почему строка, отмеченная // ???, выполняется только один раз, а не один раз для каждого типа?
  2. Есть ли способзаставить строку выполняться один раз для каждого типа и желательно без изменения определения Holder?

=================================================== Уточнения:

(ближек) реальный сценарий:

  1. struct Holder определяется в заголовке сторонней библиотеки.Тип структуры на самом деле очень сложный, и разработчик библиотеки предоставляет пользователям другой макрос:
template <bool, int> struct Holder {};

#define DEF_HOLDER(b)  Holder<b, __COUNTER__>()

В какой-то момент программы я хочу сделать «снимок» типа стекущий счетчик с помощью псевдонима типа, чтобы его можно было использовать в функции:

template <bool b>
struct Helper { using T = decltype(DEF_HOLDER(b)); };

template <bool b, typename R = typename Helper<b>::T>
R Func() {
  return R();
}

// Note that the following does not work:
// Since the 2 types generated by DEF_HOLDER do not match.
template <bool b>
auto Func() -> decltype(DEF_HOLDER(b)) {
  return DEF_HOLDER(b);
}

Проблема здесь в том, что следующие 2 использования имеют несовместимую семантику, как показано:

int main() {
  auto a = DEF_HOLDER(true);
  auto b = DEF_HOLDER(true);
  auto c = Func<true>();
  auto d = Func<true>();

  std::cout << (typeid(a) == typeid(b)) << std::endl;  // prints 0
  std::cout << (typeid(c) == typeid(d)) << std::endl;  // prints 1

  return 0;
}

InВ моем случае важно, чтобы при множественном вызове Func возвращались разные типы, как это происходит при непосредственном вызове DEF_HOLDER.

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Я не уверен, полностью ли я понимаю проблему, но, начиная с C ++ 14, нет необходимости использовать DEF_HOLDER два раза.Также работает следующий код:

template <bool b>
auto Func() {
   return DEF_HOLDER(b);
}

Если вы хотите, чтобы для каждого вызова функции требовался другой тип, вы можете добавить параметр int:

template <bool b, int i>
auto Func()
{
  return Holder<b, i>();
}

Вы можете скрыть это int в макросе.:

#define FUNC(b)  Func<b,__COUNTER__>();

Тогда a, b и c, d имеют одинаковую семантику:

int main() {
  auto a = DEF_HOLDER(true);
  auto b = DEF_HOLDER(true);
  auto c = FUNC(true);
  auto d = FUNC(true);

  std::cout << (typeid(a) == typeid(b)) << std::endl;  // prints 0
  std::cout << (typeid(c) == typeid(d)) << std::endl;  // prints 0

  return 0;
}
0 голосов
/ 06 февраля 2019

Символ __COUNTER__ - это макрос препроцессора , расширенный только один раз .

Это означает, что T будет всегда будетHolder<0> (поскольку __COUNTER__ начинается с нуля), независимо от типа, используемого для шаблона Helper.

См., Например, эту предопределенную ссылку на макрос GCC для получения дополнительной информации о __COUNTER__.

...