C++ 创建具有给定大小的n维向量
所以,我想要的是创建给定类型的多维向量,其中第一个维度将具有函数调用的第一个参数的大小,等等,例如,如果我这样做的话C++ 创建具有给定大小的n维向量,c++,templates,c++11,variadic-templates,template-meta-programming,C++,Templates,C++11,Variadic Templates,Template Meta Programming,所以,我想要的是创建给定类型的多维向量,其中第一个维度将具有函数调用的第一个参数的大小,等等,例如,如果我这样做的话 std::size_t n = 5; auto x = make_vector<int>(n + 1, n * 2, n * 3); 它似乎适用于1或2个参数,但在3个参数中失败,并出现以下错误(clang++) 包含在/Users/riad/ClionProjects/for jhelper/output/run.cpp文件中:1: /Users/riad/Cli
std::size_t n = 5;
auto x = make_vector<int>(n + 1, n * 2, n * 3);
它似乎适用于1或2个参数,但在3个参数中失败,并出现以下错误(clang++)
包含在/Users/riad/ClionProjects/for jhelper/output/run.cpp文件中:1:
/Users/riad/ClionProjects/for jhelper/tasks/TaskC.cpp:12:12:错误:调用“make_vector”时没有匹配函数
自动x=生成向量(n+1,n*2,n*3);
^~~~~~~~~~~~~~~~
/Users/riad/ClionProjects/for jhelper/tasks/。/spcpl/make_vector.hpp:9:6:注意:忽略候选模板:替换失败[with T=int,Args=]:调用函数“make_vector”,该函数在模板定义中既不可见,也无法通过依赖参数的查找找到
自动生成向量(std::size\t first,Args…size)->std::vector{
^ ~~~~~~~~~~~
/Users/riad/ClionProjects/for jhelper/tasks//spcpl/make_vector.hpp:4:16:注意:候选函数模板不可行:需要单个参数“size”,但提供了3个参数
标准::向量生成向量(标准::大小大小){
如果我理解正确的话,问题是当编译器试图计算make_vector的返回值时,它必须知道参数较少的vector的返回值,但无法做到。我如何解决这个问题?我通过单独计算类型来实现这一点,但这似乎不必要,尽管它很短
template <typename T, int n>
struct NDVector {
typedef std::vector<typename NDVector<T, n - 1>::type> type;
};
template <typename T>
struct NDVector<T, 0> {
typedef T type;
};
template <typename T>
std::vector<T> make_vector(std::size_t size) {
return std::vector<T>(size);
}
template <typename T, typename... Args>
typename NDVector<T, sizeof...(Args) + 1>::type make_vector(std::size_t first, Args... sizes) {
typedef typename NDVector<T, sizeof...(Args) + 1>::type Result;
return Result(first, make_vector<T>(sizes...));
}
模板
结构NDVector{
typedef std::向量类型;
};
模板
结构NDVector{
T型;
};
模板
标准::向量生成向量(标准::大小大小){
返回标准::向量(大小);
}
模板
typename NDVector::type make_vector(std::size_t first,Args…size){
typedef typename NDVector::type结果;
返回结果(首先,生成向量(大小…);
}
将非常欣赏更优雅的解决方案创建一个名称空间,在其中放置一些助手,称为
详细信息
在details
中创建一个类型struct adl\u helper{};
创建make_vector
的实现,但其第一个参数始终是名为Adl
的模板参数。此模板参数从不命名,其实例将传递给递归
通过调用details::make_vector(details::adl_helper{},blah)
实现make_vector(blah)
有趣的问题!您遇到的问题是,非限定名称查找将在使用它的范围内查找(按一般性的递增顺序)。但是,从[basic.scope.pdecl]: 名称的声明点紧跟在其完整声明符(第8条)之后,在其完整声明符之前 初始值设定项(如有) 在这个函数中:
template <typename T, typename... Args>
auto make_vector(std::size_t first, Args... sizes)
-> std::vector<decltype(make_vector<T>(sizes...))> {
...
}
在name函数体中,可以进行递归调用,而不会出现任何问题
如果没有C++14,您可以将其转发到一个类模板,该类模板的名称将在所有递归调用的范围内:
template <typename T, size_t N>
struct MakeVector
{
template <typename... Args>
static auto make_vector(std::size_t first, Args... sizes)
-> std::vector<decltype(MakeVector<T, N-1>::make_vector(sizes...))>
{
auto inner = MakeVector<T, N-1>::make_vector(sizes...);
return std::vector<decltype(inner)>(first, inner);
}
};
template <typename T>
struct MakeVector<T, 1>
{
static std::vector<T> make_vector(std::size_t size) {
return std::vector<T>(size);
}
};
template <typename T, typename... Args>
auto make_vector(Args... args)
-> decltype(MakeVector<T, sizeof...(Args)>::make_vector(args...))
{
return MakeVector<T, sizeof...(Args)>::make_vector(args...);
}
模板
结构生成向量
{
模板
静态自动生成向量(std::size\t first,Args…size)
->向量
{
自动内部=生成向量::生成向量(大小;
返回std::vector(第一个,内部);
}
};
模板
结构生成向量
{
静态std::vector生成向量(std::size\u t size){
返回标准::向量(大小);
}
};
模板
自动生成向量(Args…Args)
->decltype(MakeVector::make_vector(args…)
{
返回MakeVector::make_向量(args…);
}
当我发布这篇文章时,我不知道其他答案。如果对某人有用,我不会删除它。当然,启用C++14后,解决方案非常简单
使用[以下代码](您可以实现:
size_t n = 5;
auto x = make_vector<int>(n+1, n*2, n*3);
size\u t n=5;
自动x=生成向量(n+1,n*2,n*3);
以下是注释最少的代码:
// Creating a multidimensional container (e.g. `vector`, `map`)
template<template<typename...> class Container,
typename T,
size_t DIMENSION>
struct MultiDimensional
{
using internal = MultiDimensional<Container, T, DIMENSION-1>;
using type = Container<typename internal::type>;
template<typename... Args>
static
type Generate (const size_t size, Args... sizes)
{
return type(size, internal::Generate(sizes...));
}
};
// Last dimension overload
template<template<typename...> class Container,
typename T>
struct MultiDimensional<Container, T, 1>
{
using internal = T;
using type = Container<T>;
static
type Generate (const size_t size)
{
return type(size);
}
};
// Wrapper for the specific requirement of creating a multidimensional `std::vector`
template<typename T,
typename... Args>
auto make_vector(Args... sizes)
-> typename MultiDimensional<std::vector, T, sizeof...(sizes)>::type
{
return MultiDimensional<std::vector, T, sizeof...(sizes)>::Generate(sizes...);
}
//创建多维容器(例如`vector`、`map`)
模板
多维结构
{
使用内部=多维;
使用类型=容器;
模板
静止的
类型生成(常量大小、参数…大小)
{
返回类型(大小,内部::生成(大小…);
}
};
//最后维度重载
模板
多维结构
{
使用内部=T;
使用类型=容器;
静止的
类型生成(常量大小\u t大小)
{
返回类型(大小);
}
};
//用于创建多维`std::vector的特定需求的包装器`
模板
自动生成向量(参数…大小)
->typename多维::类型
{
返回多维::生成(大小…);
}
解决这个问题的最简单方法是回到C:
void foo(size_t n) {
int (*threeDArray)[2*n][3*n] = malloc((n + 1)*sizeof(*threeDArray));
//Do with your array whatever you like.
//Here I just initialize it to zeros:
for(size_t i = 0; i < n + 1; i++) {
for(size_t j = 0; j < 2*n; j++) {
for(size_t k = 0; k < 3*n; k++) {
threeDArray[i][j][k] = 0;
}
}
}
free(threeDArray);
}
void foo(大小){
int(*threeDArray)[2*n][3*n]=malloc((n+1)*sizeof(*threeDArray));
//你可以随意使用你的阵列。
//在这里,我只是将其初始化为零:
对于(大小i=0;i
正如我所说,C++中不可能这样做:C++标准要求所有的数组大小都是编译时常数。C在这方面更灵活,允许运行C99数组,无论是在代码< TyPulf< /Cord>S.< /P>内,都能运行时数组大小。
因此,当我有一些代码需要认真处理多维数组时,我会认真地问自己,是否值得将这些代码移到纯.c文件中,并将其与我的项目的其余部分链接在一起。@Columbo,你能不能eleborate?你是否认真考虑过
vector
?如果你需要多维数组,使用一个一维的,并包装它。哦,我不知道,一个大幅度的性能提高?减少不必要的间接?技术上强制的边界一致性?vec
template <typename T, typename... Args>
auto make_vector(std::size_t first, Args... sizes)
{ /* exactly as before */ }
template <typename T, size_t N>
struct MakeVector
{
template <typename... Args>
static auto make_vector(std::size_t first, Args... sizes)
-> std::vector<decltype(MakeVector<T, N-1>::make_vector(sizes...))>
{
auto inner = MakeVector<T, N-1>::make_vector(sizes...);
return std::vector<decltype(inner)>(first, inner);
}
};
template <typename T>
struct MakeVector<T, 1>
{
static std::vector<T> make_vector(std::size_t size) {
return std::vector<T>(size);
}
};
template <typename T, typename... Args>
auto make_vector(Args... args)
-> decltype(MakeVector<T, sizeof...(Args)>::make_vector(args...))
{
return MakeVector<T, sizeof...(Args)>::make_vector(args...);
}
size_t n = 5;
auto x = make_vector<int>(n+1, n*2, n*3);
// Creating a multidimensional container (e.g. `vector`, `map`)
template<template<typename...> class Container,
typename T,
size_t DIMENSION>
struct MultiDimensional
{
using internal = MultiDimensional<Container, T, DIMENSION-1>;
using type = Container<typename internal::type>;
template<typename... Args>
static
type Generate (const size_t size, Args... sizes)
{
return type(size, internal::Generate(sizes...));
}
};
// Last dimension overload
template<template<typename...> class Container,
typename T>
struct MultiDimensional<Container, T, 1>
{
using internal = T;
using type = Container<T>;
static
type Generate (const size_t size)
{
return type(size);
}
};
// Wrapper for the specific requirement of creating a multidimensional `std::vector`
template<typename T,
typename... Args>
auto make_vector(Args... sizes)
-> typename MultiDimensional<std::vector, T, sizeof...(sizes)>::type
{
return MultiDimensional<std::vector, T, sizeof...(sizes)>::Generate(sizes...);
}
void foo(size_t n) {
int (*threeDArray)[2*n][3*n] = malloc((n + 1)*sizeof(*threeDArray));
//Do with your array whatever you like.
//Here I just initialize it to zeros:
for(size_t i = 0; i < n + 1; i++) {
for(size_t j = 0; j < 2*n; j++) {
for(size_t k = 0; k < 3*n; k++) {
threeDArray[i][j][k] = 0;
}
}
}
free(threeDArray);
}