除了模板之外还有其他c ++元编程方案吗?

时间:2011-01-11 20:12:35

标签: c++ templates metaprogramming

我一直在使用元编程,但有时c宏和模板的组合还不够。

如果元编程平台仅用于Linux等,我认为缺点可能是缺乏跨平台兼容性。

所以是的,除了模板之外,现在还有这样的东西吗?谷歌搜索元编程主要是模板元编程,因此现在很难找到..

编辑:这是我一直在努力的一个例子。

假设我有一个用于在缓冲区中保存/加载文件的泛型类。我们称之为FilePack。

我有一个定义宏,看起来像

  defineFilePack(BaseClass, "code-a")

它基本上创建了一个名为“BaseClassPack”的类,它被定义为一个子类。以下是那件事。

class FilePack{
   public:
      char * thebuffer;
      int bufsize;
      string packcode;

      // and constructors etc
      FilePack(const string& thecode, int bufsize);
      void operator=(FilePack& rhs);
      void saveToFile(const string& filename);
      void loadFromFile(const string& filename);
      // .. and all the function you'd expect to see in a class like this

};

// the person details

class PersonDetails{
   public:
      solidstring<64> name;
      int age;
      DateTime birthday;
      // .. yada yada yada
};


defineFilePack(PersonDetails, "psd")

// the above creates the following class

class PersonDetailsPack : public FilePack{
   public:
      PersonDetailsPack():
         FilePack("psd", sizeof(PersonDetails)){ // etc

      }

      PersonDetails& get(){
         return *(PersonDetails*)getBuffer();
      }

      // and a lot more convenience function

};

现在,FilePack的构造函数实际上是使用全局映射对声明的代码与大小匹配的内置检查。

现在我对如何使用模板元编程难以理解,这实际上非常适合它,因为所有这些文件包代码都在源文件中声明。当然,有人可以在运行时制作自己的FilePack,但除此之外。

元编程可以帮助的另一件事是支持加载不同版本的FilePack。假设我必须更新PersonDetails类。我只是创建一个新类,使用某种元编程来声明继承,并且神奇地使FilePack知道,这样当它加载旧版本的PersonDetails时它可以调用转换函数,或者不管。

此外,欢迎您对该架构发表评论,我很想听到有关它的任何评论,但它可能有点偏离主题?

5 个答案:

答案 0 :(得分:5)

您还可以使用预处理器进行元编程。

您可以考虑使用专用预处理器来生成代码作为“元编程”。然后你可以包括像lex / yacc和Qt MOC这样的东西。

答案 1 :(得分:2)

在语言中,您只能使用模板或宏来进行元编程。例如,Boost预处理器库提供的​​元编程功能,它实现了一些真正令人惊叹的宏作为宏,非常强大。

但是,如果你想要更多一些,你可以使用你选择的脚本语言进行元编程。

答案 2 :(得分:2)

如果您将元编程定义为编写生成代码的代码,那么您有

  • 模板。
  • 预处理器。
  • 其他预处理(通常是脚本,但有时是编译器扩展)
  • 从C ++代码生成C ++源代码,动态编译,加载为共享库。
  • 可能,但是它正在拉伸它,也会生成机器代码,比如蹦床存根。

我认为最有趣的不是模板或C ++预处理器,是支持交叉关注编程的语言扩展,aspect-oriented programming,比如,记录方法调用或序列化。

我记得ParcPlace为此做了一个工具吗?

嗯,这提醒我不要忘记检查一下。 : - )

干杯&amp;第h。,

答案 3 :(得分:1)

我认为这项工作对于Python来说是完美的。简单的方法是使用自定义文件格式来描述类的制作方式,然后生成实现和接口(即使是多种语言)。

解析现有的C ++头文件实际上是一种噩梦,因为复杂的C ++语法...(以及为什么要限制自己想要表达的内容?)。

Python本身就是多平台,语言非常好......

作为示例,以下是我使用的“扩充”C ++的示例...

//
// U8 -> F32 format converter
//
//    - src(Image:U8) ............ source image
//    - dst(pImage:F32:src) ...... destination image
//
ImgFilter u8_to_f32(Image& src, Image& dst)
{
    const double k = 1.0/255;
    for (int y=0; y<src.h; y++)
    {
        unsigned char *rp = src.u8(0, y);
        float *wp = dst.f32(0, y);
        for (int x=0,w=src.w; x<w; x++)
            *wp++ = *rp++ * k;
    }
}

函数和名称/参数上方的注释由python脚本读取,该脚本为函数生成.h,处理内存分配的C ++代码,大小和格式兼容性检查,命令行参数解析,联机帮助和python绑定。 基本上我只能写“肉”并为我生成所有样板。执行此操作的python脚本是200行,并且考虑到生成的代码量,只有几个过滤器的C ++样板已经不止于此。

答案 4 :(得分:0)

如果要对代码执行任意操作,则需要通用的元编程工具,例如程序转换系统。这些工具接受源代码,并使用类似编译器的技术根据您的需要对该代码进行任意分析/修改。

我们的 DMS Software Reengineering Toolkit就是这样一个系统。它通过对要处理的编程语言的明确描述以及您希望它在源代码上执行的任务进行参数化。 DMS在这方面是独一无二的(Jackpot是一个仅限Java的程序转换系统),并且具有强大的C++ Front End,在生产C ++系统上用于大规模转换任务,具有双重独特性。

使用前端,DMS可以解析源代码以抽象语法树,构建符号表,使用直接用C ++术语编写的模式执行模式匹配或代码转换,并使用注释和文本的原始格式重新生成可编译的源代码(用数字基数等表示)。您的程序修改可以是您可以在AST上定义的任何计算。简而言之,它可以从语言之外的语言支持的元编程功能无法做到。