3

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.

Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271

2 Answers2

3

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)
ex-bart
  • 1,352
  • 8
  • 9
1

Here is my attempt on my own question:

  #include <algorithm>
  #include <cstring>

  //catch all
  template <typename T>
  void Copy(T &x, T y)
  {
      x = y;
  }

  //overload on static array copying
  //(T[N] = T[N])
  template <typename T, size_t N>
  void Copy(T(&x)[N], T(&y)[N])
  {
      std::copy(std::begin(y), std::end(y), std::begin(x));
  }

  //overload on copying of null terminated data
  //(char array = cstring)
  void Copy(char x[], const char y[])
  {
      //assumes x is >= to y
      //not sure if I can use strncpy somewhow
      strcpy(x, y); 
  }
Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271
  • I'd recommend `strncpy`. You can use `sizeof(x)` to get its size, then use that as the third argument in `strncpy`. – Moon Aug 25 '15 at 17:06
  • 1
    @Phixle `sizeof(x)` will return the size of a pointer to char, not the length of the array. In the parameter list of a function declaration, `char x[]` is exactly equivalent to `char *x`, and `x` is indeed a pointer in the function body. – ex-bart Aug 25 '15 at 17:10
  • @ex-bart Whoops, sorry. Well, my point stands: find the length of the x array and use that as the third argument of `strncpy()`. It's much safer than `strcpy`, pretty much all of the time. – Moon Aug 25 '15 at 17:14