Подтвердить что ты не робот

Шаблоны Variadic

С++ 0x позволит шаблону принимать произвольное количество аргументов. Каково наилучшее использование этой функции, кроме реализации кортежей?

4b9b3361

Ответ 1

  • Безопасный тип печати
  • Переадресация произвольных аргументов конструктора в factory методах
  • Наличие произвольных базовых классов позволяет устанавливать и удалять полезные политики.
  • Инициализация путем перемещения гетерогенных типизированных объектов непосредственно в контейнер с помощью конструктора varadical template.d.
  • Наличие литерал-оператора, который может вычислять значение для заданного пользователем литерала (например, "10110b" ).

Пример 3:

template<typename... T> struct flexible : T... { flexible(): T()... { } };

Пример 4:

struct my_container { template<typename... T> my_container(T&&... t) { } };
my_container c = { a, b, c };

Пример 5:

template<char... digits>
int operator "" b() { return convert<digits...>::value; }

Смотрите этот пример кода: здесь

Ответ 2

Возможно, разговор Андрея Александреску о событии Going Native 2012 будет интересен:

Здесь находится видео и Здесь документация.

Ответ 3

  • Типовой printf

Ответ 4

Разрешая такие вещи, как Boost.Function, принимать произвольное количество параметров

Ответ 6

Я реализовал NDArray (N-мерный массив) и имеет метод setSizes с переменным количеством аргументов. Использование переменных аргументов шаблона является более безопасным, чем использование аргументов вариационной функции, более того, я могу контролировать количество параметров, переданных этой функции во время компиляции, только с переменными аргументами шаблона.

void setSizes(uintmax_t currentSize) {
    static_assert(1 == NDimensions, "Invalid count of arguments given to setSizes.");

    size_ = currentSize;
    data_ = new NDArrayReferenceType[currentSize];
}

template <typename... Sizes>
void setSizes(uintmax_t currentSize, Sizes... sizes) {
    static_assert(sizeof...(Sizes) + 1 == NDimensions, "Invalid count of arguments given to setSizes.");

    size_ = currentSize;
    data_ = new NDArrayReferenceType[currentSize];

    for (uintmax_t i = 0; i < currentSize; i++) {
        data_[i]->setSizes(sizes...);
    }
}

Я также применил универсальную оболочку конструктора для собственного самодельного SmartPointer. Он охватывает весь пользовательский конструктор типа необработанного указателя.

template <typename TSmartPointer, typename... Args>
static inline void initialize(TSmartPointer *smartPointer, Args... args) {
    smartPointer->pointer_ = new typename TSmartPointer::PointerType(std::forward<Args>(args)...);
    smartPointer->__retain();
}

Этот код кажется неочевидным, это часть инициализатора SmartPointer для случая, должен ли SmartPointer автоматически вызывать конструктор указателя при приобретении SmartPointer (RAII). В случае абстрактных классов он не может вызвать конструктор.

Итак, если у меня есть тип AbstractObject, который является SmartPointer абстрактного класса, и тип ConcreteObject, который является SmartPointer класса с конструктором, который принимает два ints, я могу написать следующий код:

AbstractObject object = ConcreteObject(42, 42);

Это похоже на С# и Java (но с RAII), и он работает для меня в С++/GCC 4.8 =)

Ответ 7

Введите безопасность каждого вызова с динамическим номером аргумента.

Ответ 8

В других ответах упоминается безопасный тип printf, но более общие вариационные шаблоны могут использоваться для реализации функций форматирования, которые не требуют передачи информации о типе через спецификаторы формата. Например, библиотека формата С++ реализует функции форматирования, подобные Python str.format:

fmt::print("I'd rather be {1} than {0}.", "right", "happy");

в дополнение к безопасной печати. Типы аргументов записываются автоматически с использованием вариационных шаблонов в С++ 11.

Это делает ненужными спецификаторы printf, такие как lld или пресловутый PRIdPTR, а вместо

std::printf("Local number: %" PRIdPTR "\n\n", someIntPtr);

можно просто использовать

fmt::printf("Local number: %d\n\n", someIntPtr);

Отказ от ответственности. Я являюсь автором этой библиотеки