#c #types #sum
#c #типы #сумма
Вопрос:
есть ли какой-либо способ заставить функции принимать только векторы целых чисел (int, unsigned int, uint32_t и т.д.) И только их? я пытаюсь написать простую функцию, которая возвращает сумму всех значений с одинаковым типом возвращаемого значения (поскольку я не могу быть уверен, будет ли значение больше (2 ^ 32 — 1). однако, поскольку у std::vector<T>
нее нет cout
оператора для всего типа, я не могу этого сделать sum(vector<vector<T> >)
, поскольку он вернет vector (игнорируя тот факт, что vector vector не работает). я не хочу перегружать каждый тип для cout чего-либо, потому что мне это не понадобится. я просто хочу, чтобы функция работала, когда T является некоторой формой int (и float, если возможно)
я пытался использовать try/except
, но codeblocks улавливает операторы типов, поэтому я не могу скомпилировать, если я выполняю sum(vector <vector <T> >)
template <typename T>
T sum(std::vector <T> in){
try{
T total = 0;
for(int x = 0; x < in.size(); x )
total = in[x];
return total;
}
catch (int e){
std::cout << "Error " << e << " has occured." << std::endl;
exit(e);
}
}
Комментарии:
1. если
T
это интегральный тип, то невозможно, чтобы в вашем коде был выданint
.2. я еще не знаком с использованием try / catch
3. Я предлагаю никогда не использовать их, пока вы не узнаете, для чего они предназначены. Как правило, чем меньше их в вашем коде, тем лучше.
4. К вашему сведению — если ваш
sum()
шаблон создан для типа, для которогоT total = 0
недопустимо, то вы получите ошибку компилятора. Ситуации никогда не разрешается задерживаться и проявляться во время выполнения, когда выполняются исключения и блоки try / catch. C не выполняет компиляцию во время выполнения. Отдельно взятие вашего входного вектора поconst
ссылке предотвращает создание временной копии всего контейнера при каждом вызове функции… Gene иллюстрирует это, но не объясняет и не оправдывает.
Ответ №1:
template <typename T>
typename std::enable_if<
std::is_integral<typename std::remove_reference<T>::type>::value,
T>::type
sum(const std::vector<T>amp; in) { return std::accumulate(in.begin(), in.end(), 0); }
Комментарии:
1. Не может иметь
std::vector
ссылок (не то чтобы это делало ваш код недопустимым).2. @Luc: правильно, после ввода этих вещей снова и снова это стало почти автоматическим 🙂
Ответ №2:
SFINAE приходит на помощь.
#include <type_traits>
//#include <tr1/type_traits> // for C 03, use std::tr1::
template<bool, class T = void>
struct enable_if{};
template<class T>
struct enable_if<true,T>{
typedef T type;
};
template<class T>
typename enable_if<
std::is_arithmetic<T>::value,
T
>::type sum(std::vector <T> in){
T total = 0;
for(int x = 0; x < in.size(); x )
total = in[x];
return total;
}
Комментарии:
1. оба решения выдают ошибки с
error: 'enable_if' in namespace 'std' does not name a type
2. @calccrypto Вы включили
<type_traits>
так, как это указано в ответе Xeo? Знает ли ваш компилятор C 0x?3. ДА. я пробовал оба. я также включил c 0x, и он отправляет меня в сумасшедшие места, говоря, что есть ошибки (вероятно, из-за новых правил)
4. calccrypto: трудно диагностировать проблемы C 0x без надлежащей информации о коде и сообщении об ошибке. Избегая C 0x, хотя, вероятно, это доставляет больше хлопот, чем того стоит, если вы еще не используете boost, boost также предоставляет совместимый с C 03
enable_if
шаблон иis_arithmetic<>
другие тесты, Которые вы могли бы использовать….5. если вы хотите включить как целочисленную, так и с плавающей запятой, вы можете просто использовать
std::is_arithmetic<T>