声明高维向量的更简洁方法

时间:2018-10-25 08:24:56

标签: c++ c++11 templates template-meta-programming

我不喜欢这样称呼3维向量:

std::vector<std::vector<std::vector<value_type>>>

更何况我想拥有4维甚至更高的尺寸。

有没有办法使用模板元编程或某种技术来声明具有更高可读性的高维向量?

例如,能够像这样声明一个高维向量(仅作为示例):

t_vector<5, {10, 2, 2, 2, 2}, int> a;

并得到容量为[10] [2] [2] [2] [2]的

是否可以做这样的事情? 还是为什么不呢?

2 个答案:

答案 0 :(得分:5)

在您的示例中,您需要的是std::array而不是std::vector,因为后者没有固定的长度。

您可以使用递归来专门化模板:

template<class T, size_t... Ns> struct foo;

template<class T, size_t N0, size_t... Ns>
struct foo<T, N0, Ns...> {
    using type = std::array<typename foo<T, Ns...>::type, N0>;
};

template<class T>
struct foo<T> {
    using type = T;
};

template<class T, size_t... Ns>
using multiarray_t = typename foo<T, Ns...>::type;

static_assert(
        std::is_same_v<
            multiarray_t<int, 3, 2, 5>,
            std::array<std::array<std::array<int, 5>, 2>, 3>
            >
        );

编辑:

如果您要使用给定大小初始化std::vector,则仍然可以使用类似的方法:

template<class T, size_t... Ns> struct vec_builder;
template<class T, size_t N0, size_t... Ns>
struct vec_builder<T, N0, Ns...> {
    using type = std::vector<
        typename vec_builder<T, Ns...>::type>;
    static type build() {
        return type(N0, vec_builder<T, Ns...>::build());
    }
};
template<class T>
struct vec_builder<T> {
    using type = T;
    static type build() { return {}; }
};

int main() {
    auto vec = vec_builder<int, 3, 2, 5>::build();
    static_assert(
            std::is_same_v<
            decltype(vec),std::vector<std::vector<std::vector<int>>>
            >);
    assert(vec.size() == 3);
    assert(vec[0].size() == 2);
    assert(vec[1][0].size() == 5);
}

答案 1 :(得分:0)

您可以使用typedef,它只为类型创建别名,例如

typedef std::vector<std::vector<std::vector<int>>> iVector3d;

从现在开始,您只需要使用iVector3d而不是那丑陋的东西,并且C ++将在运行代码时将iVectord3替换为实际的定义,因此没有其他改变。

缺点是您必须指定类型,就像我对那里的int所做的一样。但优点是与模板相比,它超级易于使用。