More elegant way to make a C++ member function change different member variables based on template p
- by Eric Moyer
Today, I wrote some code that needed to add elements to different container variables depending on the type of a template parameter.  I solved it by writing a friend helper class specialized on its own template parameter which had a member variable of the original class.  It saved me a few hundred lines of repeating myself without adding much complexity.  However, it seemed kludgey.  I would like to know if there is a better, more elegant way.
The code below is a greatly simplified example illustrating the problem and my solution.  It compiles in g++.
#include <vector>
#include <algorithm>
#include <iostream>
namespace myNS{
  template<class Elt>
  struct Container{
    std::vector<Elt> contents;
    template<class Iter>
    void set(Iter begin, Iter end){
      contents.erase(contents.begin(), contents.end());
      std::copy(begin, end, back_inserter(contents));
    }
  };
  struct User;
  namespace WkNS{
    template<class Elt>
    struct Worker{
      User& u;
      Worker(User& u):u(u){}
      template<class Iter>
      void set(Iter begin, Iter end);
    };
  };
  struct F{ int x; explicit F(int x):x(x){} };
  struct G{ double x; explicit G(double x):x(x){} };
  struct User{
    Container<F> a;
    Container<G> b;
    template<class Elt>
    void doIt(Elt x, Elt y){
      std::vector<Elt> v; v.push_back(x); v.push_back(y);
      Worker<Elt>(*this).set(v.begin(), v.end());
    }
  };
  namespace WkNS{
    template<class Elt> template<class Iter>
    void Worker<Elt>::set(Iter begin, Iter end){
      std::cout << "Set a." << std::endl;
      u.a.set(begin, end);
    }
    template<> template<class Iter>
    void Worker<G>::set(Iter begin, Iter end){
      std::cout << "Set b." << std::endl;
      u.b.set(begin, end);
    }
  };
};
int main(){
  using myNS::F; using myNS::G;
  myNS::User u;
  u.doIt(F(1),F(2));
  u.doIt(G(3),G(4));
}
User is the class I was writing.
Worker is my helper class.  I have it in its own namespace because I don't want it causing trouble outside myNS.
Container is a container class whose definition I don't want to modify, but is used by User in its instance variables.
doIt<F> should modify a. doIt<G> should modify b.
F and G are open to limited modification if that would produce a more elegant solution.  (As an example of one such modification, in the real application F's constructor takes a dummy parameter to make it look like G's constructor and save me from repeating myself.)
In the real code, Worker is a friend of User and member variables are private.  To make the example simpler to write, I made everything public.  However, a solution that requires things to be public really doesn't answer my question.
Given all these caveats, is there a better way to write User::doIt?