4

我想要一个类型,它实际上是 POD,但我希望能够指定其中的类型和类型,例如:

template<Args...>
struct POD
{
//here I would like to create depending on Args appropriate types as a members.
};

是否可以使用 C++0x 中的这个新的可变参数模板功能来做到这一点?

4

2 回答 2

0

我从未使用过 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

伙计,弄乱可变参数模板很有趣。

于 2010-11-26T12:51:40.673 回答
0

你熟悉std::tuple吗?

AFAIK 如果它的所有成员都是 POD,它就是 POD,如果我错了,那么我猜这是不可能的。

于 2010-11-27T17:36:25.567 回答