C ++模板参数通过赋值进行推导

时间:2016-01-19 05:38:18

标签: c++ templates matrix

我想要一些非常简单的东西:一个模板函数,它只包含返回类型中的模板参数,但不包含在函数参数中。然后,在调用函数时,应该从赋值中推导出模板参数。

具体来说,让我们考虑创建某个维度的MatType<T>类型的随机矩阵的函数。模板参数T是矩阵的数字类型(例如,双精度,浮点数,整数等矩阵):

template<typename T>
MatType<T>
randmat(int m, int n)
{ // create MatType<T> of size m x n, fill with random numbers and return it.}

现在由于某种原因,模板参数不能从返回类型中推断出来,因此当我使用此函数时,我必须将其称为例如。

MatType<double> M = randmat<double>(10,10);
然而,我想要解决这个问题,即调用函数

MatType<double> M = randmat(10,10);

即。让函数从返回类型MatType<double>确定模板参数。 这只是部分原因,因为我很懒,因为我的案例中的模板参数会变得冗长而令人讨厌。

这可能看起来像许多人之前提出过的一个愚蠢的问题,但除了说它不可能之外,我并没有找到任何令人满意的答案。然而,我正在使用一个名为armadillo的矩阵库,它具有完全that ability的模板函数,所以我知道它是可能的(但是对于我来说,提取它的方式过于复杂和耗时很多&# 39;从源代码完成。)

这可以通过一些特征或模板元编程来完成吗?如何在没有像randmat(10,10);

这样的分配的情况下处理函数调用

由于

4 个答案:

答案 0 :(得分:2)

你提出的问题并非完全可能,但它的某些方面可能会发挥作用&#34;偶然的&#34;取决于问题的范围。

在第

MatType<double> M = randmat(10,10);

根据M的类型推断模板参数是不可能的(在C ++中),因为根据语言规则,首先构造RHS,发生然后赋值(或复制构造)。所以在施工时,后期的操作并没有发言权。

但是,假设randmat(10, 10)返回double s的矩阵,并且MatType<T>有一个复制构造函数,对MatType<U>进行const引用(对于其他类型{ {1}})。那么这不是你所要求的,而是一个类似的底线效应。这就是BTW犰狳发生的事情。

另一个 - @jxh特别优雅的解决方案 - 是使用延迟计算,并推迟计算任何东西,直到赋值给具体类型。

我不得不说我并不为此疯狂。在您写入问题时,您可以对临时返回的对象执行操作而无需任何分配,例如

U

因此,您必须在您的代码中提交逻辑默认特定返回类型。鉴于你这样做,并且大多数代数/随机生成操作比简单的复制转换复杂得多,在这种情况下对我来说似乎是一个复杂的过度杀伤。

答案 1 :(得分:2)

更有效地实现此效果的一种方法是推迟随机值的计算,直到返回类型已知。您可以使用代理对象来实现此目的,该代理对象的唯一目的是检测分配的类型,然后使用类型相应的对象执行计算。

struct RandMatType {
    const int m_;
    const int n_;
    RandMatType (int m, int n) : m_(m), n_(n) {}
    template <typename T>
    operator MatType<T> () const {
        MatType<T> M;
        //... fill M
        return M;
    }
};

RandMatType randmat(int m, int n) {
   return RandMatType(m, n);
}

在上面的代码中,randmat()首先返回RandMatType类型的代理。然后,在赋值期间,代理对象将转换为目标类型。然后,转换运算符假定转换类型是要使用的矩阵类型。

答案 2 :(得分:1)

避免重复的简单解决方案是:

auto m = randmat<double>(10, 10);

如果您真的想使用原始提议的语法,则必须使randmat成为占位符,只是将信息传递到您知道目标类型的位置。例如:

struct randmat
{
    int x, y; 
    randmat(int x, int y): x(x), y(y) {}
};

template<typename T>
struct MatType
{
   int x, y;

   MatType(randmat r): x(r.x), y(r.y)
   {
       // call your random generation code here; can use T
   }
};

int main()
{
   MatType<double> m = randmat(10, 10);
}

答案 3 :(得分:0)

一种选择是返回MapType

MatType<int>
randmat(int m, int n)
{ // create MatType<int> of size m x n, fill with random numbers and return it.}

并有一个转换运算符来生成所需的类型

template<typename T>
struct MatType
{
   template<typename T>
   operator MatType<T>()
   {...}
};