C ++专门化模板类函数,无需复制代码

时间:2014-08-04 13:08:03

标签: c++ function class templates partial-specialization

我想写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;
}

3 个答案:

答案 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;
}

Live Example

答案 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)

您有几种选择。

  1. 使用继承,您可以在其中专门化基类模板,并仅使用派生类模板添加大量其他相同的成员函数。

  2. 声明一个部分专门化并从impl_prototype<>::g()调用的辅助类(函数对象)。这与1.非常相似,但避免继承(例如,请参阅TemplateRex的答案);

  3. 使用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); }    
    };
    
  4. 我经常使用这最后一种方法,因为它避免了所有继承问题(特别是在非平凡构造函数的情况下)和类外的任何辅助对象。

    在您的特定示例中,更简单的可能性是

    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); }   
    };