繁体   English   中英

C ++:不同类型模板函数的自定义返回值(方法)

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

动机 - 在抽象数学中,我们可以将三维交叉积推广到n维,假设对于两个向量v,w为维n ,它们的叉积将具有维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行代码中定义的某种返回类型。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM