Nicola Bonelli
Nicola Bonelli

Reputation: 8287

Variadic templates

C++0x will allow template to take an arbitrary number of arguments. What is the best use of this feature other than implementing tuples ?

Upvotes: 23

Views: 6207

Answers (8)

vitaut
vitaut

Reputation: 55685

Type-safe printf has been mentioned in other answers, but more generally variadic templates can be used to implement formatting functions that don't require passing type information via format specifiers at all. For example, the C++ Format library implements formatting functions similar to Python's str.format:

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

in addition to safe printf. The types of arguments are captured automatically using variadic templates in C++11.

This makes printf specifiers like lld or notorious PRIdPTR unnecessary and instead of

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

one can simply use

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

Disclaimer: I'm the author of this library

Upvotes: 0

PaperBirdMaster
PaperBirdMaster

Reputation: 13298

Maybe the talk by Andrei Alexandrescu on the Going Native 2012 event, will be of your interest:

Here is the video and Here the documentation.

Upvotes: 3

cppist
cppist

Reputation: 659

I have implemented an NDArray (N-dimentional array) and it has the method setSizes with variadic count of arguments. Using variadic template arguments is type safer than using variadic function arguments, moreover I can control count of parameters passed to this function in compile time only with variadic template arguments.

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

I have also implemented a universal constructor wrapper for my self-made SmartPointer. It wraps over all user-defined constructor of type of raw pointer.

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

This code seems to be inobvious, this is a part of initializer of the SmartPointer for the case whether SmartPointer should automatically call the constructor of pointer at the acquisition of the SmartPointer (RAII). In case of abstract classes it is unable to call the constructor.

So, if I have a type AbstractObject, which is SmartPointer of an abstract class, and the type ConcreteObject, which is SmartPointer of class with constructor that takes two ints, I can write following code:

AbstractObject object = ConcreteObject(42, 42);

It is like C# and Java (but with RAII) and it works for me in C++/GCC 4.8 =)

Upvotes: 1

S. Weiser
S. Weiser

Reputation: 1

Type safety of every call with dynamic argument number.

Upvotes: 0

Kerido
Kerido

Reputation: 2940

I just wrote an article on how to implement multiple COM interfaces and keep your code compact and elegant with C++0x variadic templates.

Upvotes: 2

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 507313

  1. Type-safe printf
  2. Forwarding of arbitrary many constructor arguments in factory methods
  3. Having arbitrary base-classes allows for putting and removing useful policies.
  4. Initializing by moving heterogenous typed objects directly into a container by having a variadic template'd constructor.
  5. Having a literal operator that can calculate a value for a user defined literal (like "10110b").

Sample to 3:

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

Sample to 4:

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

Sample to 5:

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

See this example code: here

Upvotes: 33

1800 INFORMATION
1800 INFORMATION

Reputation: 135433

Allowing things like Boost.Function to take arbitrary numbers of parameters

Upvotes: 2

Konrad Rudolph
Konrad Rudolph

Reputation: 546053

  • Type-safe printf

Upvotes: 2

Related Questions