В шаблонной функции C++ я могу возвратить разыменованный тип аргумента?

То, что я имею в виду, следующее. Я хочу шаблонную функцию, которая берет два векторных итератора (или два указателя на массив двойных) и возвращает двойное, которое так или иначе связано с векторными итераторами или указателями массива, которые я передаю. Однако я хочу, чтобы это работало на двойной или международное, или любой арифметический тип.

Я думаю, что мне не разрешают сказать:

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);
}

Это будет работать? Даже если так, там другой способ сделать то, что я пытаюсь сделать? (Извините, если я не был достаточно ясен.)

5
задан Shog9 17 January 2010 в 01:34
поделиться

2 ответа

Если вы хотите вернуть двойной (т. Е. Тип, который вы получите, когда разыгрываете), вы можете использовать черты итератора:

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);
}
10
ответ дан 18 December 2019 в 14:46
поделиться

Единственным реальным преимуществом является возможность его использования в операторе switch . Все остальные вещи, на которые способен перечисление, можно просто сделать с помощью простого класса ванили с помощью частного конструктора, экземпляры которого, в свою очередь, объявляются как открытые статические конечные поля рассматриваемого класса (typesafe образца). Другое преимущество перечисления, очевидно, что это делает код менее подробным, чем вы бы сделать с простым ванильным классом.

Но если я не ошибаюсь, в C++ (или это было C #?) можно использовать Последовательности в операторе switch . Таким образом, преимущество перечислений в Java ничтожно мало по сравнению с C++. Тем не менее, то же самое было предложено для Java 7, не уверен, что он сделает это.

-121--2180543-

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:

  • Type безопасности;
  • Java 5 enums может иметь поведение и реализовывать интерфейсы;
  • Java 5 enums имеют некоторые чрезвычайно легкие структуры данных, такие как EnumSet и EnumMap .

Java 5 перечисляет эти преимущества по сравнению с использованием только классов:

  • Шаблон с меньшей склонностью к ошибкам (частный конструктор, readResolve () и т.д.);
  • Семантическая корректность. Вы видите, что что-то является перечислением, и вы знаете, что это просто представляет ценность. Ты видишь класс и не уверен. Может, где-то есть статический заводской метод и т.д. Перечисления Java 5 гораздо более четко указывают на намерение.
-121--2180537-

Похоже, ваш код противоречит описанному в тексте. Если T - тип итератора, то результат итератора dereference (как вы сказали в тексте) не будет иметь тип T * (как вы, кажется, верите в код). T * - это совершенно противоположная вещь: это то, что вы получили бы, если бы вы взяли адрес вашего итератора, а не обособили его.

На самом деле, нет пути выражать «тип без ссылок» с помощью основных языковых функций C++ (может быть, decltype сделает это в будущем, как в decltype (* T ()) ).Единственный способ описать результат отмены привязки типа T - использовать библиотечное решение: итераторные черты, как объяснил Йоханнес в своём ответе.

3
ответ дан 18 December 2019 в 14:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: