问题
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
回答1:
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 :).
回答2:
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.
回答3:
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();
}
来源:https://stackoverflow.com/questions/347096/how-can-i-get-a-specialized-template-to-use-the-unspecialized-version-of-a-membe