Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ specialize template class function without duplicating code

I want to write 5 different classes, each of which has many member functions which are exactly the same, except of one, which is special for each class. Can I write this avoiding code duplication?

Regards, Aleksejs

Below is a very shortened version of my code, which throws the error:

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;
}
like image 615
Aleksejs Fomins Avatar asked Aug 04 '14 13:08

Aleksejs Fomins


2 Answers

Member functions of class templates can be explicitly specialized but not partially specialized.

Just make a helper function object that you can partially specialize:

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

and then call that helper (the tempoary function object will optimized away):

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

like image 94
TemplateRex Avatar answered Nov 19 '22 09:11

TemplateRex


An other method is Tag dispatching, something like:

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>());}
};
like image 42
Jarod42 Avatar answered Nov 19 '22 09:11

Jarod42