C代码生成

前端之家收集整理的这篇文章主要介绍了C代码生成前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在我的史诗般的追求中,使C做事情不应该,我试图把一个编译时生成的类放在一起.

基于预处理器定义,如(粗略概念)

CLASS_BEGIN(Name)  
    RECORD(xyz)  
    RECORD(abc)

    RECORD_GROUP(GroupName)  
        RECORD_GROUP_RECORD(foo)  
        RECORD_GROUP_RECORD(bar)  
    END_RECORDGROUP   
END_CLASS

虽然我相当确定我生成一个类,使用这种结构从文件系统读取数据(也许甚至使用模板元编程),我看不到如何生成两个函数来访问数据,功能读取数据.

我想要结束一个这样的类

class Name{
    public:
    xyz_type getxyz();
    void setxyz(xyz_type v);

    //etc

    list<group_type> getGroupName();

    //etc

    void readData(filesystem){
         //read xyz
         //read abc
         //etc
    }
};

有人有任何想法,如果这是可能的吗?

– 编辑 –

澄清这个的预期用途.我有一个标准格式的文件我想要阅读.格式已经被定义了,所以它不是可以改变的.每个文件可以包含任何数字记录,每个记录可以包含任何数量的子记录.

许多记录类型每个都包含一组不同的子记录,但它们可以被定义.因此,例如Heightmap记录必须包含一个Heightmap,但可以包含法线.

所以我想要这样定义一个记录:

CLASS_BEGIN(Heightmap)  
    RECORD(VHDT,Heightmap,std::string) //Subrecord Name,Readable Name,Type  
    RECORD_OPTIONAL(VNML,Normals,std::string)  
END_CLASS

我想要输出一些类似于这样的类的功能

class Heightmap{
    public:
    std::string getHeightmap(){
        return mHeightmap->get<std::string>();
    }
    void setHeightmap(std::string v){
        mHeight->set<std::string>(v);
    }

    bool hasNormal(){
        return mNormal != 0;
    }
    //getter and setter functions for normals go here

    private:
    void read(Record* r){
        mHeightmap = r->getFirst(VHDT);
        mNormal = r->getFirst(VNML);
    }


    SubRecord* mHeightmap,mNormal;
}

我遇到的问题是我需要每次预处理定义两次.一次用于在类中定义函数定义,一次用于创建读取函数.由于预处理器是纯功能的,我无法将数据推送到队列,并在END_CLASS marco定义上生成类.

我看不出有关这个问题的方法,但是想知道有没有更了解C的人.

解决方法

您可能可以使用boost tuples解决这个问题.它将导致与现在想到的不同的设计,但它应该允许您以通用的方式解决问题.

以下示例定义了“std :: string,bool”形式的记录,然后从流中读取该数据.

#include "boost/tuple/tuple.hpp"
#include <iostream>
#include <sstream>

using namespace ::boost::tuples;

这些功能用于从istream读取数据.我们达到最后一个记录类型后,第一个重载通过元组停止迭代:

//
// This is needed to stop when we have no more fields
void read_tuple (std::istream & is,boost::tuples::null_type )
{
}

template <typename TupleType>
void read_tuple (std::istream & is,TupleType & tuple)
{
  is >> tuple.template get_head ();
  read_tuple (is,tuple.template get_tail ());
}

以下类实现了我们的记录的getter成员.使用RecordKind作为我们的关键,我们得到我们感兴趣的具体成员.

template <typename TupleType>
class Record
{
private:
  TupleType m_tuple;

public:
  //
  // For a given member - get the value
  template <unsigned int MBR>
  typename element <MBR,TupleType>::type & getMember ()
  {
    return m_tuple.template get<MBR> ();
  }

  friend std::istream & operator>> (std::istream & is,Record<TupleType> & record)
  {
    read_tuple (is,record.m_tuple);
  }
};

下一个类型是我们记录的元描述.枚举给我们一个象征性的名字,我们可以用来访问成员,即.字段名称.元组然后定义了这些字段的类型:

struct HeightMap
{
  enum RecordKind
  {
    VHDT,VNML
  };

  typedef boost::tuple < std::string,bool
                     > TupleType;
};

最后,我们构建一个记录,并从流中读取一些数据:

int main ()
{
  Record<HeightMap::TupleType> heightMap;
  std::istringstream iss ( "Hello 1" );

  iss >> heightMap;

  std::string s = heightMap.getMember < HeightMap::VHDT > ();
  std::cout << "Value of s: " << s << std::endl;


  bool b = heightMap.getMember < HeightMap::VNML > ();
  std::cout << "Value of b: " << b << std::endl;
}

而且这是所有的模板代码,你应该能够将记录嵌套在记录中.

猜你在找的C&C++相关文章