Я столкнулся с этой проблемой ранее сегодня.В следующем коде:
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>
одного типа, что заставляет меня задуматься:
- Почему строка, отмеченная
// ???
, выполняется только один раз, а не один раз для каждого типа? - Есть ли способзаставить строку выполняться один раз для каждого типа и желательно без изменения определения Holder?
=================================================== Уточнения:
(ближек) реальный сценарий:
-
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
.