Тип математики с плавающей запятой, которая может быть реализована на цифровом компьютере, обязательно использует приближение реальных чисел и операций над ними. (Стандартная версия стандартная работает до более чем пятидесяти страниц документации и имеет комитет для рассмотрения ее ошибок и дальнейшего уточнения.)
Это приближение представляет собой смесь приближений разного типа, каждый из которых можно либо игнорировать, либо тщательно учитывать из-за его конкретного способа отклонения от точности. Это также включает в себя ряд явных исключительных случаев как на уровне аппаратного обеспечения, так и на уровне программного обеспечения, которое большинство людей прогуливает прямо мимо, делая вид, что не замечает.
Если вам нужна бесконечная точность (например, вместо числа π одного из его более коротких резервных копий), вы должны написать или использовать символическую математическую программу.
Но если вы в порядке с идеей о том, что иногда математика с плавающей запятой нечеткая по значению и логике и ошибки могут быстро накапливаться, и вы можете написать свои требования и тесты для этого, тогда ваш код может часто проходить с помощью того, что находится в вашем FPU.
Шаблоны Variadic являются частью стандарта C ++ 0x, который еще официально не выпущен. Они поддерживаются gcc с версии 4.3, но вам нужно включить поддержку C ++ 0x, добавив компилятор -std = c ++ 0x.
другой синтаксис: расширение, например
template<typename VAL, typename... KEYS>
class MyMaps
{
typedef std::tuple< std::map<KEYS,VAL>... > Maps;
}
, следовательно:
MyMaps<int,int,string>:Maps
теперь фактически:
std::tuple<std::map<int,int>,std::map<string,int> >
Это пример вариационных шаблонов, которые я выставил в своем блоге: http://thenewcpp.wordpress.com/2011/11/23/variadic-templates-part-1-2/
Он компилируется. Он демонстрирует поиск самого большого типа из группы типов.
#include <type_traits>
template <typename... Args>
struct find_biggest;
//the biggest of one thing is that one thing
template <typename First>
struct find_biggest<First>
{
typedef First type;
};
//the biggest of everything in Args and First
template <typename First, typename... Args>
struct find_biggest<First, Args...>
{
typedef typename find_biggest<Args...>::type next;
typedef typename std::conditional
<
sizeof(First) >= sizeof(next),
First,
next
>::type type;
};
Одним из самых простых возможных примеров является следующая реализация max
, которая даже не шаблонна для типов.
int maximum(int n)
{
return n;
}
template<typename... Args>
int maximum(int n, Args... args)
{
return max(n, maximum(args...));
}
Только немного сложнее каноническая реализация printf
:
void printf(const char *s)
{
while (*s)
{
if (*s == '%' && *(++s) != '%')
throw "invalid format string: missing arguments";
std::cout << *s++;
}
}
template<typename T, typename... Args>
void printf(const char* s, T value, Args... args)
{
while (*s)
{
if (*s == '%' && *(++s) != '%')
{
std::cout << value;
printf(s, args...); // call even when *s == 0 to detect extra arguments
return;
}
std::cout << *s++;
}
throw "extra arguments provided to printf";
}
Очень простой пример вариационного шаблона:
Предположим, мы хотим иметь функцию, которая принимает переменное количество аргументов и печатает их все. Для ex:
print("Hello", 1, 3.14, 5L);
Для этой функциональности нам потребовались бы в основном две функции:
Первая, функция, которая принимает переменное число аргументов:
template<typename T, typename... Args>
void print(T t, Args ...args){
std::cout << t << ", ";
print(args...);
}
Некоторые объяснения:
1.) Пакеты параметров, обозначенные ellipsis (...), которые отображаются в списке параметров.
typename...Args
| | << Optional whitespace. Can have multiple whitespaces in between them
Args...args
Это означает, что все они одинаковы .
typename ...args
typename...args
typename ... args
Итак, вам не нужно беспокоиться о правильной позиции пробелов. Хотя в качестве наилучшей практики следует использовать ИМО не более одного пробела.
2.) Расширение пакета: шаблон, за которым следует многоточие.
print(args...); //expand when you wish to use them
3.) Пакет параметров принимает нулевые или более шаблонные аргументы. Таким образом, print(T t, Args... args)
принимает один или несколько аргументов .
Как только вы это понимаете, мы можем визуализировать поток вызовов, как показано ниже:
print("Hello", 1, 3.14, 5L);
означает:
print(string, int, float, long);
, который вызывает
print(int, float, long);
, который вызывает
print(float, long); // say Level 2
, который вызывает
print(long); // say Level 1
, который вызывает
print(); // say Level 0
Если вы внимательно следили за точкой № 3, вы должны были понять, что print(T t, Args... args)
не может обрабатывать вызов на уровне 0. Поэтому нам нужна другая функция здесь с тем же именем догоняйте на любом уровне> = 0.
Во-вторых, функция захватывает вызов в верхней части стека вызовов:
Catch на уровне 0:
void print(){}
или, Поймать на уровне 1:
template<typename T>
void print(T t){ std::cout << t;}
или, Поймать на уровне 2:
template<typename T, typename U>
void print(T t, U u){ std::cout << t << ", " << u;}
и так далее ...
Любое из них будет работать. Надеюсь, это поможет вам в следующий раз, когда вы начнете писать такую функцию или класс.
Шаблоны Variadic - это функция C ++ 0x, которая в первую очередь нацелена на авторов общих библиотек. Я бы не ожидал увидеть их в «коде пользователя». Например, в стандартной библиотеке C ++ 0x они используются во многих местах: std :: function, std :: async, std :: reference_wrapper, std :: tuple, std :: packaged_task, ...
Чтобы дать вам пример, я покажу вам, как может быть реализована reference_wrapper в отношении вариационных шаблонов:
template<class T>
class reference_wrapper
{
T *ptr;
public:
explicit reference_wrapper(T& thing) : ptr(&thing) {}
explicit reference_wrapper(T&& ) = delete;
operator T&() const {return *ptr;}
template<class... Args>
decltype( declval<T&>()(declval<Args>()...) )
operator()(Args&&... args) const
{
return (*ptr)(forward<Args>(args)...);
}
};
Это не совсем соответствует стандарту, но предполагается для компиляции с небольшими изменениями. Он демонстрирует несколько функций C ++ 0x:
decltype
declval
для создания объектов с целью создания выражения для decltype
(GCC пока не предлагает этот шаблон функции. необходимо записать это самостоятельно) Цель шаблона вариационного элемента - переслать аргументы объекту, указанному в ptr
. Это должно работать в случае, если T - тип указателя функции или тип класса с перегруженным оператором вызова функции.
cheers! с
До C ++ 11 вы можете создать шаблон только с фиксированным количеством параметров.
Форматировать шаблон для функции с одним параметром.
Второй шаблон для функции с два параметра. ... ie
Так как C ++ 11 вы можете написать только один шаблон, компилятор будет генерировать нужную функцию.
Хороший пример http: //eli.thegreenplace. нетто / 2014 / VARIADIC-шаблоны-в-с /