Предположим, у меня есть функция, которая выглядит следующим образом:
template <class In, class In2>
void func(In first, In last, In2 first2);
Я бы хотел, чтобы эта функция вызывала другую функцию, которая принимает предикат. Моим первоначальным инстинктом было сделать что-то вроде этого:
template <class In, class In2>
void func(In first, In last, In2 first2) {
typedef typename std::iterator_traits<In>::value_type T;
other_func(first, last, first2, std::less<T>());
}
Но есть проблема, что если In
и In2
являются итераторами разных типов? Например, char*
против int*
. В зависимости от того, какое значение равно In
, а какое In2
, предикат может усекать значения во время сравнения. Например, если In
равно char*
, то будет вызываться std::less<char>
, даже если In2
является int*
.
Когда ::operator<
задается два параметра, компилятор может определить правильный тип, и применяются стандартные правила продвижения типов. Тем не менее, при выборе предиката для передачи в функцию, нет возможности сделать это. Есть какой-нибудь умный способ выяснить, какую версию std::less<>
я хочу передать, основываясь на In
и In2
?
EDIT:
Следующий пример иллюстрирует проблему:
unsigned int x = 0x80000000;
unsigned char y = 1;
std::cout << std::less<unsigned char>()(x, y) << std::endl;
std::cout << std::less<unsigned int>()(x, y) << std::endl;
выведет:
1
0
EDIT
Подумав об этом, я действительно хотел бы сделать что-то вроде этого:
typedef typeof(T1() < T2()) T;
other_func(first, last, first2, std::less<T>());
Полагаю, я мог бы использовать расширение __typeof__
в gcc ..., но мне тоже не нравится эта идея. Есть ли способ получить этот чистый эффект стандартным, согласованным способом?