通过模板实现结构体成员拷贝-按成员名匹配
# c++17 版本
#include <stdio.h>
#include <iostream>
#include <functional>
#include <type_traits>
#include <string.h>
using namespace std;
#define RegisterHasMember(MemName) \
template<typename T, typename=void> \
struct HasMember_##MemName : std::false_type {}; \
template<typename T> \
struct HasMember_##MemName<T, std::void_t<decltype(T::MemName)>> : std::true_type {}; \
/**
* expand:
* template<typename T, typename=void>
* struct HasMember_A : std::false_type {};
* template<typename T>
* struct HasMember_A<T, std::void_t<decltype(T::A)>> : std::true_type {};
*/
RegisterHasMember(A)
RegisterHasMember(B)
RegisterHasMember(sid)
RegisterHasMember(tid)
RegisterHasMember(stype)
RegisterHasMember(ttype)
RegisterHasMember(stra)
RegisterHasMember(strb)
RegisterHasMember(AAA)
RegisterHasMember(BBB)
#define COPY_ONE_MEMBER(tmen, smen) \
if constexpr(HasMember_##tmen<Tar>::value && HasMember_##smen<Src>::value) { \
tar.tmen = src.smen; \
}
#define COPY_ONE_MEMBER_WITH_FUNC(tmen, smen, func) \
if constexpr(HasMember_##tmen<Tar>::value && HasMember_##smen<Src>::value) { \
func(tar.tmen, src.smen); \
}
template<typename Tar, typename Src>
void copy_member(Tar &tar, Src &src)
{
/**
* expand:
* if constexpr(HasMember_tid<Tar>::value && HasMember_sid<Src>::value) {
* tar.tid = src.sid;
* }
*/
COPY_ONE_MEMBER(tid, sid);
COPY_ONE_MEMBER(ttype, stype);
COPY_ONE_MEMBER(B, A);
COPY_ONE_MEMBER(BBB, AAA);
COPY_ONE_MEMBER_WITH_FUNC(strb, stra, strcpy);
}
struct ALogin {
int sid;
char stype;
int A;
char stra[9];
};
struct BLogin {
long tid;
char ttype;
int B;
char strb[9];
};
int main() {
cout<< "ALogin has member A: " << HasMember_A<ALogin>::value <<endl;
cout<< "BLogin has member A: " << HasMember_A<BLogin>::value <<endl;
ALogin alogin {3, 5, 7, "dummy"};
BLogin blogin{};
copy_member(blogin, alogin);
printf("after copy, blogin: %d,%d,%d,%s\n",
blogin.tid, blogin.ttype, blogin.B, blogin.strb);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# c++11 版本
#include <stdio.h>
#include <type_traits>
#include <string.h>
using namespace std;
// c++17 can use std::void_t
template< class... >
struct void_st {
using type = void;
};
// copy Dst.dm from Src.sm
#define REGISTER_COPY_MEMBER(dm, sm) \
template<typename Dst, typename Src, typename=void, typename=void> \
struct copy_member_##dm##_from_##sm { \
static void docopy(Dst &dst, Src &src) {} \
}; \
template<typename Dst, typename Src> \
struct copy_member_##dm##_from_##sm < Dst, Src, typename void_st<decltype(Dst::dm)>::type, typename void_st<decltype(Src::sm)>::type > { \
static void docopy (Dst &dst, Src &src) { \
dst.dm = src.sm; \
} \
template<typename Func> \
static void docopy (Dst &dst, Src &src, Func f) { \
f(dst.dm, src.sm); \
} \
}; \
#define COPY_ONE_MEMBER(dm, sm) copy_member_##dm##_from_##sm<Dst, Src>::docopy(dst, src)
#define COPY_ONE_MEMBER_WITH_FUNC(dm, sm, f) copy_member_##dm##_from_##sm<Dst, Src>::docopy(dst, src, f)
/**
* expand:
* template<typename Dst, typename Src, typename=void, typename=void>
* struct copy_member_B_from_A { static void docopy(Dst &dst, Src &src) {}
* };
* template<typename Dst, typename Src>
* struct copy_member_B_from_A < Dst, Src, std::void_t<decltype(Dst::B)>, std::void_t<decltype(Src::A)> > {
* static void docopy (Dst &dst, Src &src) { dst.B = src.A; }
* template<typename Func>
* static void docopy (Dst &dst, Src &src, Func f) { f(dst.B, src.A); }
* };
*/
REGISTER_COPY_MEMBER(B, A);
REGISTER_COPY_MEMBER(dtype, stype);
REGISTER_COPY_MEMBER(id, id);
REGISTER_COPY_MEMBER(strb, stra);
REGISTER_COPY_MEMBER(NotExist, NotExist);
template<typename Dst, typename Src>
static void copy_member(Dst &dst, Src &src)
{
// copy_member_B_from_A<Dst, Src>::docopy(dst, src)
COPY_ONE_MEMBER(B, A);
COPY_ONE_MEMBER(dtype, stype);
COPY_ONE_MEMBER(id, id);
COPY_ONE_MEMBER(NotExist, NotExist);
// copy_member_strb_from_stra<Dst, Src>::docopy(dst, src, strcpy)
COPY_ONE_MEMBER_WITH_FUNC(strb, stra, strcpy);
}
struct ALogin {
int A;
char stype;
int id;
char stra[9];
};
struct BLogin {
long B;
char dtype;
long id;
char strb[9];
};
int main() {
ALogin alogin {3, 5, 7, "dummy"};
BLogin blogin{};
copy_member(blogin, alogin);
printf("after copy, blogin: %d,%d,%d,%s\n",
blogin.B, blogin.dtype, blogin.id, blogin.strb);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
编辑 (opens new window)
上次更新: 2023/05/09, 01:45:50