基本上,我有很多不同类型的结构:
typedef struct
{
char memberA;
int memberB;
...
} tStructA;
是否可以使用模板从结构中获取/提取任意成员?在伪代码中,我正在寻找类似的东西:
/*This is pseudocode!*/
template <typename STRUCT_TYPE, typename MEMBER_TYPE, membername NAME>
class cMemberExtractor
{
public:
MEMBER_TYPE
extract(const STRUCT_TYPE* pStruct) const
{
return pStruct->NAME;
}
};
背后的想法是使用这样的模板:
/*somewhere*/
void
producer()
{
//produce update
tStructA* pUpdate=new tStructA;
...
//send update to receivers
emit(pUpdate);
}
/*elsewhere*/
void
consumer(const tStructA* pUpdate)
{
//extract data
int data=cMemberExtractor<tStructA,int,memberB>().extract(pUpdate);
//process data
...
}
感谢您的帮助!
答案 0 :(得分:4)
您可以使用名称但使用成员指针来执行此操作:
template <typename C, typename M>
struct updater_t {
typedef M C::*member_ptr_t;
updater_t( member_ptr_t ptr, M const & new_value )
: new_value( new_value ), ptr(ptr)
{}
updater_t( member_ptr_t ptr, C & original )
: new_value( original.*ptr ), ptr(ptr)
{}
void operator()( C & obj ) {
obj.*ptr = new_value;
}
M new_value;
member_ptr_t ptr;
};
struct test {
int value;
};
int main() {
updater_t<test,int> update( &test::value, 10 );
test object;
update( object );
test object2;
updater_t<test,int> update_copy( &test::value, object );
update_copy( object2 );
}
编辑:按照litb的建议将成员指针移动到模板参数:
template <typename C, typename M, M C::* Ptr>
struct updater_t {
updater_t( M const & new_value ) : new_value( new_value ) {}
updater_t( member_ptr_t ptr, C & original ) : new_value( original.*Ptr ) {}
void operator()( C & obj ) {
obj.*ptr = new_value;
}
M new_value;
};
int main() {
updater_t<test,int, &test::value> update( 10 );
test object;
update( object );
}
答案 1 :(得分:2)
这对我有用:
#include <iostream>
struct Foo {
int member;
Foo() : member() {}
};
template< typename T, typename C >
T& extract(C& obj, T C::* member)
{
return (obj.*member);
}
int main()
{
Foo foo;
std::cout << foo.member << '\n';
extract(foo, &Foo::member) = 42;
std::cout << foo.member << '\n';
return 0;
}
extract(Object, &Class::Member)
会在Member
中返回对Object
的引用。那是你想要的吗?
答案 2 :(得分:-1)
您需要宏的帮助。
#include <cstddef>
template <typename StructType, typename MemberType, size_t member_offset>
struct cMemberExtractor {
MemberType extract(const StructType* pStruct) const {
const char* member_loc = reinterpret_cast<const char*>(pStruct) + member_offset;
return *(reinterpret_cast<const MemberType*>(member_loc));
}
};
#define M_MEMBER_EXTRACTOR(STRU, MEMTYPE, MEMNAME) \
(cMemberExtractor<STRU,MEMTYPE,offsetof(STRU,MEMNAME)>())
...
int data = M_MEMBER_EXTRACTOR(tStructA,int,memberB).extract(pUpdate);
如果您的编译器支持typeof
运算符,则可以删除MEMTYPE
参数以帮助键入安全性。
#define M_MEMBER_EXTRACTOR(STRU, MEMNAME) \
(cMemberExtractor<STRU,typeof(((STRU*)0)->MEMNAME),offsetof(STRU,MEMNAME)>())
...
int data = M_MEMBER_EXTRACTOR(tStructA,memberB).extract(pUpdate);