C++ 需要帮助破译模板元编程宏

C++ 需要帮助破译模板元编程宏,c++,macros,template-meta-programming,C++,Macros,Template Meta Programming,我非常想亲自尝试一下,但是我在GCC和Clang上遇到了一个编译错误: Undefined symbols for architecture x86_64: "foo::_theInfo", referenced from: foo::info() in reflect-eLsDqz.o ld: symbol(s) not found for architecture x86_64 这是代码(直接在博客上发布),我希望沃特先生不介意 /* A simple C++ reflec

我非常想亲自尝试一下,但是我在GCC和Clang上遇到了一个编译错误:

Undefined symbols for architecture x86_64:
  "foo::_theInfo", referenced from:
      foo::info() in reflect-eLsDqz.o
ld: symbol(s) not found for architecture x86_64
这是代码(直接在博客上发布),我希望沃特先生不介意

/* A simple C++ reflection mark-up library. The strength 
   of this library is that it is entirely static (all the 
   reflection information is built without using dynamic 
   memory allocation), and it is exremely compact, allowing
   you to declare the members of a structure right where 
   that struct is declared, leading to minimal risk of 
   version mismatch.

   This code is placed in the public domain by Jon Watte.
   http://www.enchantedage.com/cpp-reflection
   Version 2009-04-20
*/

#include <typeinfo>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct TypeBase
{
  virtual void Marshal(void *, void const *) const = 0;
  virtual void Demarshal(void const *, void *) const = 0;
  virtual char const *name() const = 0;
  virtual size_t size() const = 0;
};

template<typename T> struct Type : TypeBase
{
  static Type<T> instance;
  // custom marshaling is handled by template specialization
  void Marshal(void *dst, void const *src) const { memcpy(dst, src, sizeof(T)); }
  void Demarshal(void const *src, void *dst) const { memcpy(dst, src, sizeof(T)); }
  char const *name() const { return typeid(T).name(); }
  size_t size() const { return sizeof(T); }
};

template <typename T> T& instance() {
  static T t;
  return t;
}

template<typename T, typename Q>
TypeBase *get_type(Q T::*mem) {
  return &instance<Type<Q> >();
}

struct member_t
{
  char const *name;
  TypeBase *type;
  size_t offset;
};

struct ReflectionBase
{
  void ReflectionConstruct();
  virtual size_t size() const = 0;
  virtual char const *name() const = 0;
  virtual size_t memberCount() const = 0;
  virtual member_t const *members() const = 0;
};

void ReflectionBase::ReflectionConstruct()
{
  //  todo: register myself in some table, etc
  members();
  memberCount();
  name();
  size();
}

#define MEMBER(x) \
   { #x, get_type(&T::x), (size_t)&((T*)0)->x },

#define RTTI(_type, _mems) \
  template<typename T> struct _info : ReflectionBase { \
    /* overrides used by ReflectionBase */ \
    inline size_t size() const { return sizeof(T); } \
    inline char const *name() const { return #_type; } \
    inline size_t memberCount() const { size_t cnt; get_members(cnt); return cnt; } \
    inline member_t const *members() const { size_t cnt; return get_members(cnt); } \
    _info() { ReflectionConstruct(); } \
    static inline member_t const *get_members(size_t &cnt) { \
      static member_t members[] = { _mems }; \
      cnt = sizeof(members) / sizeof(members[0]); \
      return members; \
    } \
    static inline _info<T> &info() { \
      return instance<_info<T> >(); \
    } \
  }; \
  inline static member_t const * members() { return _info<_type>::info().members(); } \
  static _info<_type> _theInfo; \
  inline static _info<_type> &info() { return _theInfo; }

struct foo {
  int x, y, z;
  RTTI(foo, MEMBER(x) MEMBER(y) MEMBER(z))
};

int main() {
  printf("type: %s\n", foo::info().name());
  printf("size: %ld\n", foo::info().size());
  for (size_t i = 0; i != foo::info().memberCount(); ++i) {
    printf("  %s: offset %ld  size %ld  type %s\n",
      foo::info().members()[i].name, foo::info().members()[i].offset,
      foo::info().members()[i].type->size(), foo::info().members()[i].type->name());
  }
  return 0;
}
<代码> /*一个简单的C++反射标记库。力量 这个库的特点是它是完全静态的(所有 反射信息是在不使用动态 内存分配),并且非常紧凑,允许 您需要在以下位置声明结构的成员: 声明了该结构,从而将 版本不匹配。 此代码由Jon Watte公开发布。 http://www.enchantedage.com/cpp-reflection 版本2009-04-20 */ #包括 #包括 #包括 #包括 结构类型库 { 虚拟无效封送处理(void*,void const*)const=0; 虚空数据元(虚空常数*,虚空*)常数=0; 虚拟字符常量*name()常量=0; 虚拟大小\u t size()常量=0; }; 模板结构类型:TypeBase { 静态类型实例; //自定义封送处理由模板专门化处理 无效封送处理(void*dst,void const*src)const{memcpy(dst,src,sizeof(T));} void Demarshal(void const*src,void*dst)const{memcpy(dst,src,sizeof(T));} char const*name()const{return typeid(T).name();} size_t size()常量{return sizeof(t);} }; 模板T&实例(){ 静态T; 返回t; } 模板 类型库*获取类型(Q T::*mem){ 返回&instance(); } 结构成员 { 字符常量*名称; TypeBase*类型; 尺寸偏差; }; 结构反射基 { void ReflectionConstruct(); 虚拟大小\u t size()常量=0; 虚拟字符常量*name()常量=0; 虚拟大小\u t memberCount()常量=0; 虚拟成员常量*members()常量=0; }; void ReflectionBase::ReflectionConstruct() { //托多:在某张桌子上登记一下,等等 成员(); memberCount(); 名称(); 大小(); } #定义成员(x)\ {x,get_type(&T::x),(size_T)和((T*)0)->x}, #定义RTTI(_类型,_mems)\ 模板结构_信息:ReflectionBase{\ /*ReflectionBase使用的覆盖*/\ 内联size_t size()常量{return sizeof(t);}\ 内联字符常量*name()常量{return#_type;}\ 内联大小\u t成员计数()常量{size\u t cnt;获取\u成员(cnt);返回cnt;}\ 内联成员常量*成员()常量{size\t cnt;返回get_成员(cnt);}\ _info(){ReflectionConstruct();}\ 静态内联成员\u t const*get\u成员(大小\u t&cnt){\ 静态成员_tmembers[]={u mems}\ cnt=sizeof(成员)/sizeof(成员[0])\ 返回成员\ } \ 静态内联_info&info(){\ 返回实例()\ } \ }; \ 内联静态成员_tconst*members(){return _info::info().members();}\ 静态信息\ 内联静态_info&info(){return _theInfo;} 结构foo{ int x,y,z; RTTI(foo,成员(x)成员(y)成员(z)) }; int main(){ printf(“类型:%s\n”,foo::info().name()); printf(“大小:%ld\n”,foo::info().size()); 对于(size_t i=0;i!=foo::info().memberCount();++i){ printf(“%s:偏移量%ld大小%ld类型%s\n”, foo::info().members()[i]。名称,foo::info().members()[i]。偏移量, foo::info().members()[i].type->size(),foo::info().members()[i].type->name(); } 返回0; }
因此,
static\u info\u theInfo
在上面的一行中声明,但有些东西不起作用。我想我已经接近了解这段代码的工作原理了(
MEMBER
是一个获取成员偏移量的整洁的小宏,这很有趣),但我以前从来没有必要做像在宏中放置模板类定义这样可怕的事,所以我实际上不知道从哪里开始戳这个

我发现了一个不同的版本

inline static\u info&info()\
{ \
静态信息\
返回信息\
}

这似乎很明显,但是
\u theInfo
没有在任何地方初始化。@remyabel好的,我现在明白了,但是初始化语句会是什么样子?很遗憾,我几天内都不能设置赏金;如果你能解释一下宏中最令人困惑的四分之一行(英语)的实际用途,那就是链接器错误,而不是编译器错误。哈,这是一个有用的工具:-)谢谢!我仍然有很长的路要走去理解为什么这会修复它,尽管.FWIW和g++4.8都需要这个更改来正确编译代码
inline static _info<_type> &info() \
{ \
    static _info<_type> _theInfo; \
    return _theInfo; \
}