0

I'm working on a "framework" that needs to automate processing of conversion of a framework-user-defined collection of variables from/to text.

I've defined a base class for a converting text, given a variable, and templatized it. I've coded a dozen standard types (int, unsigned int, double, string, bool, time_t, etc.) and want to now support vector of any of the types for which there's already a solution.

In short, I want to a version of this template for that works for a vector of anything, T=vector<U>, and have it work for any element type that I've already coded, including vectors of vectors of elementary objects and so on.

Here is a base class and template in a header t.h:

#pragma once
#include <string>
#include <vector>
using namespace std;

class BoundVarBase {
public:
  BoundVarBase() {};
  virtual ~BoundVarBase() {};
  virtual void FromText( const char* psz ) = 0;
  virtual void ToText( string* ps ) = 0;
};

template<typename T> class BoundVar: public BoundVarBase {
public:
  BoundVar( T& t ) :
    BoundVarBase(),
    pt( &t )
  {
  };

  virtual void FromText( const char* psz );
  virtual void ToText( string* ps );

  T* pt;
};

Here is t.cpp:

#include <iostream>
#include <t.h>

template<> void BoundVar<int>::FromText( const char* psz ) {
  *pt = strtol( psz, NULL, 0 );
}

template<> void BoundVar<int>::ToText( string* psOut ) {
  *psOut = to_string( *pt );
}

int main( int nArg, const char* apszArg[] ) {

  string s;
  int i = 123;
  BoundVar bi( i );

  bi.ToText( &s );
  cout << s << endl;

  bi.FromText( "456" );
  cout << i << endl;

  return 0;
}

Compilation and execution look like:

> g++ --std=c++17 t.cpp -g -I. -o t
> ./t
123
456

The question is what to put that might look something like this:

template<class vector<U>> class BoundVar: public BoundVarBase {
public:
  BoundVar( vector<U> U& vu ) :
    BoundVarBase(),
    pt( &t )
  {
  };

  virtual void FromText( const char* psz ) {
    // to be determined
  };
  virtual void ToText( std::string* ps ) {
    string sElement;
    *ps = "[ ";
    for ( auto& u: pvu ) {
      BoundVar bu( u );
      bu.ToText( sElement );
      *ps += sElement + " ";
    }
    *ps += " ]";
  }

  vector<U>* pvu;
};

that would allow this code

  vector<int> ai = {1, 2, 3};
  BoundVar bvi( ai );

  bvi.ToText( &s );
  cout << s << endl;

  bvi.FromText( "[ 4 5 6 ]" );
  cout << "[ " << ai[0] << " " << ai[1] << " " << ai[2] << " ]" << endl;

to output

[ 1 2 3 ]
[ 4 5 6 ]

Obviously, after getting BoundVar<int> I could just code BoundVar<vector<int>>. And with one type of binding that'd be easiest! But I have all the atomic C/C++ types, plus things like string, time_t and so on supported and want to have arrays of all those (and hopefully, arrays of arrays etc.) all supported with just one more template.

Swiss Frank
  • 1,985
  • 15
  • 33
  • 2
    Look up *partial specialization*. Something like `template class BoundVar> {};`. Or better, with `typename ...T` and `T...` to support custom allocators. Or better, a specialization that accepts *any* container (look up SFINAE and C++20 `requires`, if you can use it). – HolyBlackCat Oct 08 '22 at 17:45

0 Answers0