3

我对 c++ 很陌生,但想尝试做一些花哨的模板。我不确定这是否可能,但我相当有信心有办法实现这一目标。

所以这里的问题是:我正在调用各种硬件函数,它需要许多参数,并且只有一种参数类型不同:

int Read(HANDLE handle, int location, char* Name, int startindex1, int endindex1,
         int startindex2, int endindex2, int* rval, Astruct* callback) ;
int Read(HANDLE handle, int location, char* Name, int startindex1, int endindex1,
         int startindex2, int endindex2, double* rval, Astruct* callback) ;

硬件接口根据索引的值返回一个标量、数组或矩阵。我真正想要实现的是一个函数,它返回一个Tvector<T>vector<vector<T>>取决于我传递的参数的数量。:

                T MyReadFunction<T>(HANDLE handle, int location, char* Name,int index)
        vector<T> MyReadFunction<T>(HANDLE handle, int location, char* Name,int startindex1,
                                                                            int endindex1   )
vector<vector<T>> MyReadFunction<T>(HANDLE handle, int location, char* Name,int startindex1, 
                                                                            int endindex1
                                                                            int startindex2, 
                                                                            int endindex2)

其中T是基本类型,如int, real, float,double等。

使用 3 个具有专业化的不同模板是没有问题的,但我很想以某种方式将它们结合起来。

我的假设是,这可以使用模板专业化来实现,但我无法理解它。我想我应该是这样的:

template<typename T ,int... Indexes>
T MyReadFunction (HANDLE handle, int location, char* Name, Indexes... myIndex){}

template<>
int MyReadFunction (HANDLE handle, int location, char* Name, int myindex)
{
    int rval = 0; 
    Read (handle,location,name,myindex,myindey,0,0,&rval, NULL) ;
    return rval;
}

这是一个两头野兽。我很可能需要明确地实现我的 3 个案例以避免误用,但也想知道,我如何根据参数包的大小来实现模板专业化,参数包的大小不同。

我在 VS 2019 中使用最新的 msvc++

4

2 回答 2

2

您可以编写一个类型来创建所需等级的嵌套向量,如下所示:

template<typename T,int N> 
struct VT 
{ 
    using type = typename std::vector<typename VT<T, N - 1>::type>;
};

template<typename T> 
struct VT<T, 0> 
{ 
    using type = int;
};

然后像这样编写一个函数:

template<typename T ,typename ...Indexes>
typename VT<T, sizeof...(Indexes) / 2>::type 
  MyReadFunction (int handle, int location, char* Name, Indexes... myIndex) {}

这是一个演示

正如您所观察到的,这样做并没有多大意义,因为函数的主体将变得相当难以实现。简单地编写特化或重载将是一个更简单的解决方案。

请注意,如果您确实选择了编写此函数模板,则myIndex参数包是不受约束的,即它将接受除int. 当然,您可以通过编写更多代码来限制它。

此外,此函数模板将接受Indexes大小为 3、5、7 等,这可能不是您想要的。同样,您也可以通过编写更多代码来限制它。

于 2020-10-09T17:31:30.493 回答
0

对于这个关于参数包的问题,​​cigien 有一个很好的答案。

这是另一个不使用包的解决方案。参数包是类型列表,但您实际上不需要改变 N 种类型,您只需要一个 N 维数组。

如果将索引列表放在花括号内,则可以将其视为具有编译时长度的列表。

不过,在我看来,标量情况可能无法从多维情况中很好地概括。标量情况采用单个索引,而数组需要每个维度的开始和结束索引。

template<typename T,int N> 
struct VT 
{
    using type = typename std::vector<typename VT<T, N - 1>::type>;
};

template<typename T> 
struct VT<T, 0> 
{ 
    using type = T;
};

template< typename T, int n >
std::enable_if_t< n == 1 || n % 2 == 0,
  typename VT<T, n/2>::type >
  MyReadFunction( HANDLE handle, int location, char* Name, int const (&indexes)[n] );

// usage: MyReadFunction< double >( inputFile, 123, "name", { 1, 2, 3, 4 } );
// yields vector< vector< double > >
于 2020-10-09T18:00:34.057 回答