我想要一个类型,它实际上是 POD,但我希望能够指定其中的类型和类型,例如:
template<Args...>
struct POD
{
//here I would like to create depending on Args appropriate types as a members.
};
是否可以使用 C++0x 中的这个新的可变参数模板功能来做到这一点?
我从未使用过 C++0x 可变参数模板功能,但以下代码在 G++ 4.5 上编译:
template <typename... Args>
struct tuple;
template <typename T, typename... Args>
struct tuple<T, Args...> {
T value;
tuple<Args...> inner;
};
template <typename T>
struct tuple<T> {
T value;
};
然而,初始化它们是……很奇怪,因为我们需要嵌套内部值:
int main() {
tuple<int> n1 = { 23 };
tuple<int, float> n2 = { 42, { 0.5f } };
tuple<std::string, double, int> n3 = { "hello, world", { 3.14, { 97 } } };
}
检索值当然有点乏味。最简单的方法可能是提供一个get<N>()
函数模板。
但是我们不能get
直接实现,因为函数模板不能部分特化。要么我们需要使用 SFINAE(阅读:),要么我们需要boost::enable_if
将实际功能委托get
给可以部分特化的类型。
在下文中,我做了后者。但首先,我们需要另一个辅助类型 trait: nth_type
,它返回函数的适当返回类型get
:
template <unsigned N, typename... Args>
struct nth_type;
template <unsigned N, typename T, typename... Args>
struct nth_type<N, T, Args...> : nth_type<N - 1, Args...> { };
template <typename T, typename... Args>
struct nth_type<0, T, Args...> {
typedef T type;
};
十分简单。只返回类型列表中的第n个类型。
现在我们可以编写我们的get
函数了:
template <unsigned N, typename... Args>
inline typename nth_type<N, Args...>::type get(tuple<Args...>& tup) {
return get_t<N, Args...>::value(tup);
}
就像我说的,这只是委派了任务。没什么大不了的。在实践中,我们可能希望对const
元组有另一个重载(但实际上,我们将使用现有tuple
类型)。
现在是杀戮,然后是清淡的沙拉:
template <unsigned N, typename... Args>
struct get_t;
template <unsigned N, typename T, typename... Args>
struct get_t<N, T, Args...> {
static typename nth_type<N, T, Args...>::type value(tuple<T, Args...>& tup) {
return get_t<N - 1, Args...>::value(tup.inner);
}
};
template <typename T, typename... Args>
struct get_t<0, T, Args...> {
static T value(tuple<T, Args...>& tup) {
return tup.value;
}
};
就是这样。我们可以通过在之前定义的变量中打印一些值来测试这一点:
std::cout << get<0>(n1) << std::endl; // 23
std::cout << get<0>(n2) << std::endl; // 42
std::cout << get<0>(n3) << std::endl; // hello, world
std::cout << get<1>(n2) << std::endl; // 0.5
std::cout << get<1>(n3) << std::endl; // 3.14
std::cout << get<2>(n3) << std::endl; // 97
伙计,弄乱可变参数模板很有趣。
你熟悉std::tuple
吗?
AFAIK 如果它的所有成员都是 POD,它就是 POD,如果我错了,那么我猜这是不可能的。