То, что я имею в виду, следующее. Я хочу шаблонную функцию, которая берет два векторных итератора (или два указателя на массив двойных) и возвращает двойное, которое так или иначе связано с векторными итераторами или указателями массива, которые я передаю. Однако я хочу, чтобы это работало на двойной или международное, или любой арифметический тип.
Я думаю, что мне не разрешают сказать:
template <class T>
T* func(T Begin, T End)
T new_variable = Begin + 5;
return (*new_variable);
}
потому что компилятор не поймет то, что означает T*. Решение, о котором я думал, состоит в том, чтобы взять то, что я пытаюсь возвратить и сделать его третьим аргументом:
template <class T>
void func(T Begin, T End, T* new_variable)
new_variable = Begin + 5;
return (*new_variable);
}
Это будет работать? Даже если так, там другой способ сделать то, что я пытаюсь сделать? (Извините, если я не был достаточно ясен.)
Если вы хотите вернуть двойной (т. Е. Тип, который вы получите, когда разыгрываете), вы можете использовать черты итератора:
template<typename RandomAccessIterator>
typename std::iterator_traits<RandomAccessIterator>::value_type
func(RandomAccessIterator a, RandomAccessIterator b) {
typedef typename std::iterator_traits<RandomAccessIterator>::value_type
value_type;
// use value_type now, when you want to save some temporary
// value into a local variable, for instance
value_type t = value_type();
for(; a != b; ++a) t += *a;
return t;
}
Эти работы для всех итераторов, включая указатели:
int main() {
int d[3] = { 1, 2, 3 };
assert(func(d, d + 3) == 6);
}
Единственным реальным преимуществом является возможность его использования в операторе switch
. Все остальные вещи, на которые способен перечисление, можно просто сделать с помощью простого класса ванили с помощью частного
конструктора, экземпляры которого, в свою очередь, объявляются как открытые статические конечные
поля рассматриваемого класса (typesafe образца). Другое преимущество перечисления, очевидно, что это делает код менее подробным, чем вы бы сделать с простым ванильным классом.
Но если я не ошибаюсь, в C++ (или это было C #?) можно использовать Последовательности
в операторе switch
. Таким образом, преимущество перечислений в Java ничтожно мало по сравнению с C++. Тем не менее, то же самое было предложено для Java 7, не уверен, что он сделает это.
Java 5 перечислений произошло на основе шаблона перечисления типа Джошуа Блоха Эффективная Java (первое издание), чтобы избежать подводных камней перечислений в C/C +
В основном константы int и перечисления int не являются наборными. Вы можете передать любое значение int. В C/C + + вы можете сделать это:
enum A { one, two, three };
enum B { beef, chicken, pork } b = beef;
void func(A a) { ... }
func((A)b);
К сожалению, шаблон перечисления typesafe из Effective Java имел много шаблона, не все это очевидно. Наиболее примечательным является то, что вам пришлось переопределить метод private readResolve
, чтобы остановить создание новых экземпляров Java при десериализации, что нарушило бы простую проверку ссылок (т. е. с помощью оператора = =
вместо равно ()
).
Таким образом, Java 5 enums имеют следующие преимущества по сравнению с ints:
EnumSet
и EnumMap
. Java 5 перечисляет эти преимущества по сравнению с использованием только классов:
readResolve ()
и т.д.); Похоже, ваш код противоречит описанному в тексте. Если T
- тип итератора, то результат итератора dereference (как вы сказали в тексте) не будет иметь тип T *
(как вы, кажется, верите в код). T *
- это совершенно противоположная вещь: это то, что вы получили бы, если бы вы взяли адрес вашего итератора, а не обособили его.
На самом деле, нет пути выражать «тип без ссылок» с помощью основных языковых функций C++ (может быть, decltype
сделает это в будущем, как в decltype (* T ())
).Единственный способ описать результат отмены привязки типа T
- использовать библиотечное решение: итераторные черты, как объяснил Йоханнес в своём ответе.