如何获得专用模板来使用成员函数的非专用版本?

发布于 2024-07-09 07:00:31 字数 630 浏览 8 评论 0原文

考虑以下代码:

template <int dim>
struct vec
{
    vec normalize();
};


template <>
struct vec<3>
{
    vec cross_product(const vec& second);
    vec normalize();
};

template <int dim>
vec<dim> vec<dim>::normalize()
{
    // code to normalize vector here
    return *this;
}

int main()
{
    vec<3> direction;
    direction.normalize();
}

编译此代码会产生以下错误:

1>main.obj:错误 LNK2019:无法解析的外部符号“public: struct vec<3> __thiscall vec<3>::normalize(void)” (?normalize@?$vec@$02@@QAE?AU1@ XZ) 在函数 _main 中引用

Consider the following code:

template <int dim>
struct vec
{
    vec normalize();
};


template <>
struct vec<3>
{
    vec cross_product(const vec& second);
    vec normalize();
};

template <int dim>
vec<dim> vec<dim>::normalize()
{
    // code to normalize vector here
    return *this;
}

int main()
{
    vec<3> direction;
    direction.normalize();
}

Compiling this code produces the following error:

1>main.obj : error LNK2019: unresolved external symbol "public: struct vec<3> __thiscall vec<3>::normalize(void)" (?normalize@?$vec@$02@@QAE?AU1@XZ) referenced in function _main

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夜无邪 2024-07-16 07:00:31

你不能:)你想要的是专门化成员函数:

template <int dim>
struct vec
{
    // leave the function undefined for everything except dim==3
    vec cross_product(const vec& second);
    vec normalize();
};

template<>
vec<3> vec<3>::cross_product(const vec& second) {
    // ...
}

template <int dim>
vec<dim> vec<dim>::normalize()
{
    // code to normalize vector here
    return *this;
}

另一个稍微复杂的解决方案是使用boost::enable_if:

template <int dim>
struct vec
{
    // function can't be called for dim != 3. Error at compile-time
    template<int dim1>
    typename boost::enable_if_c< dim == dim1 && dim1 == 3, vec<dim1> >::type 
    cross_product(const vec<dim1>& second) {
        // ...
    }
    vec normalize();

    // delegate to the template version
    void without_params() {
        // delegate
        this->without_params<dim>();
    }

private:
    // function can't be called for dim != 3. Error at compile-time
    template<int dim1>
    typename boost::enable_if_c< dim == dim1 && dim1 == 3 >::type 
    without_params() {
        // ...
    }   
};

template <int dim>
vec<dim> vec<dim>::normalize()
{
    // code to normalize vector here
    return *this;
}

如果调用cross_product,这将导致编译时错误any dim != 3。请注意,“trick”仅适用于带参数的函数,因为只有这样才能自动推导模板参数。 对于没有参数的情况,我在上面提供了一个函数 without_parameters :)。

You can't :) What you want is to specialize the member functions instead:

template <int dim>
struct vec
{
    // leave the function undefined for everything except dim==3
    vec cross_product(const vec& second);
    vec normalize();
};

template<>
vec<3> vec<3>::cross_product(const vec& second) {
    // ...
}

template <int dim>
vec<dim> vec<dim>::normalize()
{
    // code to normalize vector here
    return *this;
}

Another, slightly more complicated solution is to use boost::enable_if:

template <int dim>
struct vec
{
    // function can't be called for dim != 3. Error at compile-time
    template<int dim1>
    typename boost::enable_if_c< dim == dim1 && dim1 == 3, vec<dim1> >::type 
    cross_product(const vec<dim1>& second) {
        // ...
    }
    vec normalize();

    // delegate to the template version
    void without_params() {
        // delegate
        this->without_params<dim>();
    }

private:
    // function can't be called for dim != 3. Error at compile-time
    template<int dim1>
    typename boost::enable_if_c< dim == dim1 && dim1 == 3 >::type 
    without_params() {
        // ...
    }   
};

template <int dim>
vec<dim> vec<dim>::normalize()
{
    // code to normalize vector here
    return *this;
}

That will cause a compile time error if cross_product is called for any dim != 3. Note that that 'trick' only works for functions with parameters, since only then the template parameter can be auto-deduced. For cases without parameters, i have provided a function without_parameters above :).

[旋木] 2024-07-16 07:00:31

您尚未提供 vec<3>::normalize 的定义,因此链接器显然无法链接到它。

模板专业化的全部要点是您可以提供每种方法的专业化版本。 除非在这种情况下你实际上并没有这样做。

You haven't supplied a definition of vec<3>::normalize, so the linker obviously can't link to it.

The entire point in a template specialization is that you can supply specialized versions of each method. Except you don't actually do that in this case.

半衾梦 2024-07-16 07:00:31

据我所知,你不能称之为“通用”版本。

或者,您可以将类外部的通用实现定义为函数:

template <int dim>
struct vec
{
};

namespace impl {
    template <int dim>
    vec<dim> normalize(const vec<dim>& v)
    {
        // code to normalize vector here
        return v;
    }
}

template <>
struct vec<3>
{
    vec cross_product(const vec& second);
    vec normalize() { return impl::normalize(*this); }
};


int main()
{
    vec<3> direction;
    direction.normalize();
}

You can't as far as I know call the "generic" version.

Alternatively, you can define your generic implementations outside of the classes as functions:

template <int dim>
struct vec
{
};

namespace impl {
    template <int dim>
    vec<dim> normalize(const vec<dim>& v)
    {
        // code to normalize vector here
        return v;
    }
}

template <>
struct vec<3>
{
    vec cross_product(const vec& second);
    vec normalize() { return impl::normalize(*this); }
};


int main()
{
    vec<3> direction;
    direction.normalize();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文