如何将使用参数包和类型名的类作为函数的输入参数(c++)

Posted

技术标签:

【中文标题】如何将使用参数包和类型名的类作为函数的输入参数(c++)【英文标题】:How to take a class, that uses a parameter pack and typename, as an input parameter for a function(c++) 【发布时间】:2019-11-04 14:36:53 【问题描述】:

我创建了一个接受typename 模板变量和parameter pack 的类。在下一步中,我希望能够将该类的两个对象传递给我的函数。

我的主要问题是,正确传递模板参数和对象才能使用我的函数。 我的类实现。

//auto as template parameter is for non-type parameter(c++17)
template <auto value> constexpr auto DIM = value;
//constexpr on values in header files(c++17)
inline constexpr auto const DIM3 = DIM <3>;
inline constexpr auto const DIM2 = DIM <2>;


enum Index : int lower = 0, upper = 1;


template<int base, int exponent>
int constexpr pow()
    if constexpr(exponent == 0)
        return 1;
    else
        return base * pow<base, exponent-1>();
    

template<int Size, typename T>
struct Array
    T array[Size];
    Array(const T * a)
        for(int i = 0; i < Size; i++)
            array[i] = a[i];
        
    
;



//auto as template parameter is for non-type parameters(c++17)
template<typename T = double, auto ...IndicesN>
class MatrixND

private:
    const Array<pow<DIM3, sizeof...(IndicesN)>(), T> matrix;

public:
    MatrixND(const T * arr): matrix(arr)

    template<auto ...args>
    auto constexpr getElement()
    
;

接受 MatrixND 对象的函数:

template<auto posT1, auto posT2, typename A, typename B>
auto constexpr function(const MatrixND<A> tensor1, const MatrixND<B> tensor2)

    return 0;

我尝试了以下方法,但它抛出错误消息“没有匹配的函数调用”:

const double arrayc[27] = 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27;
auto matrix1 = new MatrixND<double, upper, lower, lower>(arrayc);

function<1,1, decltype(matrix1), decltype(matrix1)>(matrix1, matrix1);

错误信息:

error: no matching function for call to ‘function<1, 1, MatrixND<double, (Index)1, (Index)0, (Index)0>*, MatrixND<double, (Index)1, (Index)0, (Index)0>*>(MatrixND<double, (Index)1, (Index)0, (Index)0>*&, MatrixND<double, (Index)1, (Index)0, (Index)0>*&)’
     contraction<1,1, decltype(matrix1), decltype(matrix1)>(matrix1, matrix1);

【问题讨论】:

auto constexpr function(const A &amp; tensor1, B const &amp; tensor2)? 旁注:pow 未声明 constexpr (并且它需要参数)所以 const Array&lt;pow&lt;DIM3, sizeof...(IndicesN)&gt;(), T&gt; matrix; 不会编译。我想你定义了自己的? @AndyG 对不起,我忘记了密码。我编辑了我的代码。 【参考方案1】:

需要在function的模板参数中添加参数包。使用

template<auto posT1, auto posT2, typename A, typename B, auto ...AIndicesN, auto ...BIndicesN>
auto constexpr function(const MatrixND<A, AIndicesN...> tensor1, const MatrixND<B, BIndicesN...> tensor2)

    return 0;

允许你调用类似的函数

auto foo = function<1,1>(matrix1, matrix1);

请注意,要使用您的代码进行编译,您需要更改

auto matrix1 = new MatrixND<double, upper, lower, lower>(arrayc);

auto matrix1 = MatrixND<double, upper, lower, lower>(arrayc);

因为您实际上并不想要指向 MatrixND 的指针,而是实际的 MatrixND 对象。

【讨论】:

【参考方案2】:

当你调用函数时

function<1,1, decltype(matrix1), decltype(matrix1)>(matrix1, matrix1);

您说模板参数ABdecltype(matrix1),这意味着它们实际上是MatrixND&lt;double, upper, lower, lower&gt;

这反过来意味着例如参数tensor1 的类型为const MatrixND&lt;MatrixND&lt;double, upper, lower, lower&gt;&gt;。这不是你通过的。

一个可能的解决方案是不在参数列表中使用MatrixND&lt;A&gt;(和MatrixND&lt;B&gt;),而只使用

template<auto posT1, auto posT2, typename A, typename B>
auto constexpr function(const A tensor1, const B tensor2)

    return 0;

您也应该将引用而不是值作为参数传递。


如果您对函数执行上述操作,您也不需要 AB 类型的模板参数,因为编译器会推断出:

function<1,1>(matrix1, matrix1);

【讨论】:

值得补充一下,可以使用类型特征和静态断言来确保AB 确实是MatrixND 当我使用const A tensor1const B tensor2 时,我无法使用我班级的功能。例如 tensor1.getElement<...>()。有什么方法可以使用我的对象功能吗? @M.Mac 为什么?这会给您带来什么问题? @Someprogrammerdude 很抱歉,它有效,但我的自动完成功能没有。

以上是关于如何将使用参数包和类型名的类作为函数的输入参数(c++)的主要内容,如果未能解决你的问题,请参考以下文章

如何将对象作为方法输入参数而不是作为参数数组传播?

我应该将啥类型添加到作为参数接收的类构造函数中?

如何将不同类型的结构体作为一个函数的参数?

c语言中的类型名和形式参数名的意义是啥

第20课 可变参数模板_模板参数包和函数参数包

将作为变量名的函数参数传递到 R 函数中的公式中?