合并相同的模板,并使用不同的功能

时间:2014-12-06 05:43:21

标签: c++ templates

我想创建一个被视为笛卡尔坐标或极坐标的矢量(数学)结构。应该只有一个结构,但会自动传递给相应的函数。

我有以下代码:

struct cartesian {};
struct polar {};

template<unsigned int N, typename format = cartesian>
struct Vec
{
    float v[N];
};

然而,虽然格式参数不会改变结构的内部结构,但我相信我最终会得到两种不同的类型,而不是一种。这不是必要的。我宁愿只需要以下两个函数,而不是两种不同的类型:

template <unsigned int N>
Vec<N, cartesian> nrm(Vec<N, cartesian> v)
{
    return v;
}

template <unsigned int N>
Vec<N, polar> nrm(Vec<N, polar> v)
{
    return v;
}

编译器根据格式模板参数确定要使用的函数。

我不确定我解释得那么好,但希望你能理解我的意思。请询问任何澄清。

有没有办法可以实现(使用模板)?

感谢。


对于R Sahu:

两个独立的功能如下:

Vec<N, cartesian> nrm(Vec<N, cartesian> v)
{
    float vLen = sqrt(v[0] * v[0] + v[1] * v[1]);

    Vec<N, cartesian> result = v;

    result[0] /= vLen; // 0 is X
    result[1] /= vLen; // 1 is Y

    return result;
}

template <unsigned int N>
Vec<N, polar> nrm(Vec<N, polar> v)
{
    Vec<N, polar> result = v;

    result[1] = 1.0F; // 1 is length of vector

    return result;
}

对不起,如果退回v;引起混淆,只是让错误检查器安静,我想删除冗长。


非模板化示例可能有所帮助:

INT CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
{
    // I believe the code is currently being compiled down to the non-template equivalent:
    // How I DON'T want it

        // 2 separate type definitions
        Vec2Car cartesianVec = { 1, 1 };
        Vec2Pol polarVec = { 0.785F, 1.41F };

        // Appropriate function is called for the type passed in
        Vec2Car cartesianNrm = nrm(cartesianVec);
        Vec2Pol polarNrm = nrm(polarVec);

    // How I DO want it

        Vec2CarPol cartesianVec = Vec<2, cartesian>(1, 1); // created with <format = cartesian>, doesn't change type definition, but compiler should know what to call below
        Vec2CarPol polarVec = Vec<2, polar> ( 0.785F, 1.41F); // as above

        // cartesianVec was created with <format = cartesian>, so use this the appropriate version of nrm();
        Vec2CarPol cartesianNrm = nrm(cartesianVec);
        // polarNrm was created with <format = polar>, so use this the appropriate version of nrm();
        Vec2CarPol polarNrm = nrm(polarVec);

    return EXIT_SUCCESS;
}

2 个答案:

答案 0 :(得分:2)

只需使用一个带有两个模板参数的函数模板。

template <unsigned int N, typename format>
Vec<N, format> nrm(Vec<N, format> v)
{
    return v;
}

或者,正如@cdhowie所建议的那样,使用

template <typename T>
T nrm(T v)
{
    return v;
}

更新,以回应更新的问题

你的功能有点令人困惑。当你使用:

result[0] /= vLen; // 0 is X
result[1] /= vLen; // 1 is Y
你是说

吗?
result.v[0] /= vLen; // 0 is X
result.v[1] /= vLen; // 1 is Y

我假设这就是你的意思。

您可以使用以下方法获得最易重复使用的代码:

template<unsigned int N, typename format = cartesian>
struct Vec
{
   typedef format Format;
   float v[N];
};

void nrm(float v[], cartesian dummy)
{
   float vLen = sqrt(v[0] * v[0] + v[1] * v[1]);
   v[0] /= vLen;
   v[1] /= vLen;
}

void nrm(float v[], polar dummy)
{
   v[1] = 1.0F;
}

template <typename T>
T nrm(T v)
{
   T result = v;
   nrm(result.v, T::Format());

   // Not sure what's the purpose of computing result.
   // It is not being returned.

   return v;
}

答案 1 :(得分:0)

只要您将format作为模板参数之一,编译器就会生成两个结构。它是允许编译器在编译时选择调用两个函数中的哪一个的类型。