Reputation: 8287
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
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
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
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
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
Reputation: 507313
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
Reputation: 135433
Allowing things like Boost.Function to take arbitrary numbers of parameters
Upvotes: 2