2015-08-25 1 views
3

Не все экземпляры типа могут быть скопированы в другой экземпляр того же типа с знаком =.Какой интерфейс будет копировать cstrings, массивы и другие типы в экземпляры одного типа?

Например, хотя он может работать на Интс:

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

Это не будет работать на массивы символов:

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

или других массивов:

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

или символ * s:

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

Как я могу написать перегруженную функцию, которая позволит мне сделать следующее?

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" 

* Я буду считать, что любые абстрактные типы данных сделать необходимую работу в их перегруженный оператор присваивания (или из мелкой копии, предоставленной компилятором)


Почему вам нужно сделай это?
Чтобы упростить проверку частей устаревшей базы кода C, я хотел бы сгенерировать некоторые обертки C++ вокруг нескольких компонентов. Из-за странного дизайна кода С, существует много косвенности, от которой я хотел бы избавиться. Таким образом, было бы намного проще копировать переменные в другой экземпляр, используя простую функцию Copy вместо того, чтобы разбирать типы и решать, как сделать соответствующую копию в другой переменной экземпляра.

+2

.... Dont? Используйте 'std :: string' и' std :: vector', тогда вы можете просто сделать 'x = y' ... –

+1

Почему вы считаете, что назначение указателя (' char * ') было бы неправильным? Это работает отлично. И что пытаются решить? – DarkDust

+0

@Ben Я взаимодействую с устаревшим кодом C. –

ответ

1

Вот моя попытка на мой собственный вопрос:

#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); 
    } 
+0

Я бы рекомендовал' strncpy'. Вы можете использовать 'sizeof (x)' для получения своего размера, а затем использовать это как третий аргумент в 'strncpy'. – Phixle

+1

@Phixle 'sizeof (x)' будет возвращать размер указателя на char, а не длину массива. В списке параметров объявления функции 'char x []' точно эквивалентен 'char * x', а' x' действительно является указателем в теле функции. –

+0

@ ex-bart Увы, извините. Ну, моя точка зрения: найдите длину массива x и используйте это как третий аргумент 'strncpy()'. Это намного безопаснее, чем 'strcpy', почти все время. – Phixle

3

Вот полный пример, с cout s посыпают, чтобы показать, что правильные перегрузках выбраны.

#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" 
    } 
} 

Выход:

g++ -std=c++11 -g -Wall -O3 check.cc -o check && ./check 
assign (default) 
assign (array) 
assign (array) 
assign (pointer) 
Смежные вопросы