我想写5个不同的类,每个类都有许多成员函数完全相同,除了一个,这对每个类都是特殊的。我可以写这个避免代码重复吗?
此致 Aleksejs
以下是我的代码的缩短版本,它会引发错误:
template_test.cpp:15:35: error: invalid use of incomplete type ‘class impl_prototype<cl, 1>
#include <iostream>
using namespace std;
template <int cl, int dim>
class impl_prototype {
public:
impl_prototype() {}
int f(int x) { return cl + 2 * g(x); }
int g(int x) { return cl + 1 * x;}
};
template <int cl>
int impl_prototype<cl, 1>::g(int x) { return cl + 3 * x; }
int main ()
{
impl_prototype<0, 0> test_0;
impl_prototype<0, 1> test_1;
cout << test_0.f(5) << " " << test_0.g(5) << std::endl;
cout << test_1.f(5) << " " << test_1.g(5) << std::endl;
return 0;
}
答案 0 :(得分:3)
类模板的成员函数可以是显式专用的,但不是部分专用的。
只需创建一个可以部分专门化的辅助函数对象:
#include <iostream>
using namespace std;
template<int cl, int dim>
struct g_impl
{
int operator()(int x) { return cl + 1 * x;}
};
template<int cl>
struct g_impl<cl, 1>
{
int operator()(int x) { return cl + 3 * x; }
};
然后调用那个帮助器(暂时的函数对象将被优化掉):
template <int cl, int dim>
class impl_prototype
{
public:
impl_prototype() {}
int f(int x) { return cl + 2 * g(x); }
int g(int x) { return g_impl<cl, dim>()(x); }
};
int main ()
{
impl_prototype<0, 0> test_0;
impl_prototype<0, 1> test_1;
cout << test_0.f(5) << " " << test_0.g(5) << std::endl;
cout << test_1.f(5) << " " << test_1.g(5) << std::endl;
return 0;
}
答案 1 :(得分:3)
另一种方法是标签调度,类似于:
template <int cl, int dim>
class impl_prototype
{
int g(int x, std::integral_constant<int, 1>) { return cl + 3 * x; }
template <int I>
int g(int x, std::integral_constant<int, I>) { return cl + 1 * x; }
public:
int f(int x) { return cl + 2 * g(x); }
int g(int x) { return g(x, std::integral_constant<int, dim>());}
};
答案 2 :(得分:0)
您有几种选择。
使用继承,您可以在其中专门化基类模板,并仅使用派生类模板添加大量其他相同的成员函数。
声明一个部分专门化并从impl_prototype<>::g()
调用的辅助类(函数对象)。这与1.非常相似,但避免继承(例如,请参阅TemplateRex的答案);
使用SFINAE来&#34;专攻&#34;成员函数:
template<int cl, int dim>
class impl_prototype
{
template<bool dim_equals_one> typename std::enable_if<!dim_equals_one,int>::type
_g(const int x) const { return cl+1*x; }
template<bool dim_equals_one> typename std::enable_if< dim_equals_one,int>::type
_g(const int x) const { return cl+3*x; }
public:
int f(const int x) const { return cl+2*g(x); }
int g(const int x) const { return _g<dim==1>(x); }
};
我经常使用这最后一种方法,因为它避免了所有继承问题(特别是在非平凡构造函数的情况下)和类外的任何辅助对象。
在您的特定示例中,更简单的可能性是
template<int cl, int dim>
class impl_prototype
{
public:
int f(const int x) const { return cl + 2 * g(x); }
int g(const int x) const { return cl + (dim==1? 3*x : x); }
};