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;
}
                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
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>());}
};
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With