Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What interface will copy cstrings, arrays, and other types to instances of the same type?

Not all instances of a type can be copied to another instance of the same type with an = sign.

For example, although it may work on ints:

int x = 0;
int y = 5;
x = y; //x is now: 5

It would not work on char arrays:

char x[32]="data to overwrite";
char y[32]="new data";
x = y; //incorrect

or other arrays:

int x[5] = {1,2,3,4,5};
int y[5] = {6,7,8,9,10};
x = y; //incorrect

or char*s:

char* x="data to overwrite";
char* y="new data";
x = y; //incorrect

How can I write an overloaded function that will allow me to do the following?

int x = 0;
int y = 5;
Copy(x,y); //x is now: 5

char x[32]="data to overwrite";
char y[32]="new data";
Copy(x,y); //x is now: "new data"

int x[5] = {1,2,3,4,5};
int y[5] = {6,7,8,9,10};
Copy(x,y); //x is now: {6,7,8,9,10}

char* x="data to overwrite";
char* y="new data";
Copy(x,y); //x is now: "new data"

*I'll assume that any abstract data types do the necessary work in their overloaded assignment operator(or from the shallow copy provided by the compiler)


Why do you need to do this?
In order to easier test portions of a legacy C code base, I'd like to generate some C++ wrappers around a few components. Due to the strange design of the C code, there is a lot of indirection that I would like to get rid of. As such, it would be a lot easier to copy variables into another instance using a simple Copy function instead of parsing out the types, and deciding how to make the appropriate copy into the other instance variable.

like image 492
Trevor Hickey Avatar asked Nov 04 '25 11:11

Trevor Hickey


1 Answers

Here is a complete example, with couts sprinkled in to show that the correct overloads are selected.

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <ostream>

// default
template<class T>
void Assign(T& dst, const T& src)
{
  dst = src;
  std::cout << "assign (default)" << std::endl;
}

// arrays
template<class T1, std::size_t n>
void Assign(T1 (&dst)[n], const T1 (&src)[n])
{
  std::copy(src, src+n, dst);
  std::cout << "assign (array)" << std::endl;
}

// pointers
template<class T1>
void Assign(T1 *&dst, T1 *src)
{
  // DANGER: memory leaks/double frees
  // not exactly sure what is supposed to happen here
  // same as default for now...
  // ok as long as only string constants are passed around
  // (as is the case in the example)
  dst = src;
  std::cout << "assign (pointer)" << std::endl;
}

int main() {
  {
    int x = 0;
    int y = 5;
    Assign(x,y); //x is now: 5
  }

  {
    char x[32]="data to overwrite";
    char y[32]="new data";
    Assign(x,y); //x is now: "new data"
  }

  {
    int x[5] = {1,2,3,4,5};
    int y[5] = {6,7,8,9,10};
    Assign(x,y); //x is now: {6,7,8,9,10}
  }

  {
    const char* x="data to overwrite";
    const char* y="new data";
    Assign(x,y); //x is now: "new data"
  }
}

Output:

g++ -std=c++11 -g -Wall -O3 check.cc -o check && ./check
assign (default)
assign (array)
assign (array)
assign (pointer)
like image 163
ex-bart Avatar answered Nov 06 '25 02:11

ex-bart