C :不同类型的模板功能(方法)的自定义返回值

C++: Custom return value for different types of template function (method)

本文关键字:方法 返回值 自定义 功能 同类型      更新时间:2023-10-16

动机 - 在抽象数学中,我们可以将3维交叉产品推广到n个维度,假设对于dimension n的两个向量v,w,它们的交叉产品将具有尺寸n(n-1)/2。跳过差异形式的想法,我想将此想法交谈为C 库中模板的语言。我有这个主意:

auto Cross(const Vec<dim, float_t> &rhs) {
    if (dim == 0)return;
    if (dim == 1)return (float_t)0;
    if (dim == 2)return Values[0] * rhs.Values[1] - Values[1] * rhs.Values[0];
    if (dim == 3)return Vec<dim, float_t>(
        Values[1] * rhs.Values[2] - Values[2] * rhs.Values[1], 
        Values[2] * rhs.Values[0] - Values[0] * rhs.Values[2], 
        Values[0] * rhs.Values[1] - Values[1] * rhs.Values[0]);
    //...
}

,但可悲的是,auto指示符不允许使用不同的返回类型。我当然可以与预处理器混乱,但是我相信有更多聪明的方法,例如:

Vec<dim*(dim-1)/2,float_t> Cross(const Vec<dim,float_t> &rhs);

(用void作为零维点的特殊情况,而float_t仅适用于一维点)。如何以明智的方式解决这个问题?

我相信您可以做到这一点:

template <std::size_t dim>
auto cross(const Vec<dim, float_t>& rhs)
{
    /*logic goes here, also you can generalize*/    
}

这将为每个dim(隐式)创建新功能。另外,尝试在编译时间而不是通过使用专业来进行运行时进行操作。

通过专业化来构造这种情况的一种方法。没有专业化,将很难实现真正的通用模板算法(我很感兴趣)。

如果您使用专业知识,则大部分时间都不能使用auto,则必须明确返回类型。这应该做您想要的:

#include<cassert>
#include<array>
using std::array;
template<std::size_t Dim>
array<double, Dim*(Dim-1)/2> 
Cross(array<double, Dim> const&, array<double, Dim> const&);
template<> array<double, 0> Cross(
    array<double, 1> const&, array<double, 1> const& v2
){return {};}
template<> array<double, 1> Cross(
    array<double, 2> const& v1, array<double, 2> const& v2
){return {{v1[0] * v2[1] - v1[1] * v2[0]}};}
template<> array<double, 3> Cross(
    array<double, 3> const& v1, array<double, 3> const& v2
){
    return {{
        v1[1] * v2[2] - v1[2] * v2[1], 
        v1[2] * v2[0] - v1[0] * v2[2], 
        v1[0] * v2[1] - v1[1] * v2[0]
    }};
}
int main(){
    array<double, 1> v1{{1.}};
    array<double, 2> v2{{1.,2.}};
    array<double, 3> v3{{1.,2., 3.}};
    assert(( Cross(v1, v1) == array<double, 0>{} ));
    assert(( Cross(v2, v2)[0] == 0. ));
    assert(( Cross(v3, v3)[0] == 0. ));
}

现在,在这一点上,如果您知道您将使用(总计)专业(如上述),则Cross的此和单独的过载之间几乎没有区别(除了执行第6行中定义的某个返回类型除外代码。)