我想要一些非常简单的东西:一个模板函数,它只包含返回类型中的模板参数,但不包含在函数参数中。然后,在调用函数时,应该从赋值中推导出模板参数。
具体来说,让我们考虑创建某个维度的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);
?
由于
答案 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>()
{...}
};