C++0x 将允许模板采用任意数量的参数。除了实现元组之外,此功能的最佳用途是什么?
8 回答
- 类型安全的 printf
- 在工厂方法中转发任意多个构造函数参数
- 拥有任意基类允许放置和删除有用的策略。
- 通过具有可变参数模板的构造函数将异构类型对象直接移动到容器中进行初始化。
- 具有可以计算用户定义的文字(如“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; }
请参阅此示例代码:here
- 类型安全
printf
允许诸如 Boost.Function 之类的东西采用任意数量的参数
我刚刚写了一篇关于如何实现多个 COM 接口并使用 C++0x 可变参数模板保持代码紧凑和优雅的文章。
我已经实现了一个 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,我可以编写以下代码:
AbstractObject object = ConcreteObject(42, 42);
它就像 C# 和 Java(但带有 RAII),它适用于 C++/GCC 4.8 =)
使用动态参数号键入每个调用的安全性。
其他答案中提到了类型安全的 printf ,但更普遍的是,可变参数模板可用于实现根本不需要通过格式说明符传递类型信息的格式化函数。例如,C++ Format 库实现了类似于 Python 的str.format的格式化函数:
fmt::print("I'd rather be {1} than {0}.", "right", "happy");
除了安全的 printf。使用 C++11 中的可变参数模板自动捕获参数类型。
这使得 printf 说明符 like lld
or notoriousPRIdPTR
不必要,而不是
std::printf("Local number: %" PRIdPTR "\n\n", someIntPtr);
可以简单地使用
fmt::printf("Local number: %d\n\n", someIntPtr);
免责声明:我是这个库的作者