Boost препроцессорная библиотека для генерации набора типов на основе списка базовых типов, например PointI32, PointF32 и т. Д. В C ++ / CLI - PullRequest
1 голос
/ 08 февраля 2010

Я пытаюсь выяснить, как использовать библиотеку Boost.Preprocessor http://www.boost.org/doc/libs/release/libs/preprocessor, чтобы развернуть «универсальный» тип для различных конкретных типов. Ниже я спрошу это для простого примера класса пункта. Дано:

struct Point##TYPE_SUFFIX_NAME
{
    TYPE X;
    TYPE Y;

    // Other code
};

Я хочу сгенерировать этот тип для разных базовых (POD) типов данных, например ::100100

PointF32, PointF64, PointI32 etc.

где PointF32 будет:

struct PointF32
{
     float X;
     float Y;
};

То есть на основе списка типов:

short, int, long, float, double etc. 

Я хочу "раскрыть" вышеприведенный тип для них. Желательно с определением «шаблона» в отдельном включаемом файле, а не в виде макроса, чтобы упростить отладку.

ПРИМЕЧАНИЕ. Мне не интересно слышать о шаблонах C ++. Я знаю, как использовать шаблоны. Но это не полезно в моем случае. В качестве примера представьте, что эти типы будут использоваться из .NET в C #, но генерируются в C ++ / CLI. Поэтому, пожалуйста, придерживайтесь вопроса.

Проблема, конечно же, связана с отсутствием поддержки шаблонов в .NET и из-за того, что универсальные шаблоны не подходят для решения моей проблемы.

Ответы [ 4 ]

1 голос
/ 08 февраля 2010

Следующий код не проверен , но должен стать хорошим началом для достижения желаемого.

В my_structures.h:

#ifndef __MYSTRUCTURES_H__
#define __MYSTRUCTURES_H__

#define MY_LIST_OF_TYPES (F32, (I32, (BOOST_PP_NIL)))
#define MY_LIST_OF_SUFFICES (float, (int, (BOOST_PP_NIL)))

#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/list/size.hpp>

#define BOOST_PP_ITERATION_LIMITS (0, BOOST_PP_LIST_SIZE(MY_LIST_OF_TYPES))
#define BOOST_PP_FILENAME_1       "create_my_structures.h"
#include BOOST_PP_ITERATE()

#undef MY_LIST_OF_TYPES
#undef MY_LIST_OF_SUFFICES
#endif

и в create_my_structures.h

#include <boost/preprocessor/list/at.hpp>

#define n BOOST_PP_ITERATION()

struct Point ## BOOST_PP_LIST_AT(MY_LIST_OF_SUFFICES, n)
{
  BOOST_PP_LIST_AT(MY_LIST_OF_TYPES, n) X;
  BOOST_PP_LIST_AT(MY_LIST_OF_TYPES, n) Y;
};

#undef n
1 голос
/ 09 февраля 2010

Основываясь на ответе Бенуа, я придумал следующий ответ. Ответ состоит из трех файлов:

  • MyPointTypes.h
  • MyPointTypeImpl.h
  • MyPointTypes.cpp

MyPointTypes.h:

#ifndef __MYSTRUCTURES_H__
#define __MYSTRUCTURES_H__

#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/seq/size.hpp>

typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef signed int int32;
typedef unsigned int uint32;
typedef signed int int64;
typedef unsigned int uint64;

typedef float float32;
typedef double float64;

#define MY_SIGNED_INTEGER_SEQ    (int8)(int16)(int32)(int64)
#define MY_SIGNED_INTEGER_SUFFIX_SEQ    (I8)(I16)(I32)(I64)

#define MY_UNSIGNED_INTEGER_SEQ    (uint8)(uint16)(uint32)(uint64)
#define MY_UNSIGNED_INTEGER_SUFFIX_SEQ    (UI8)(UI16)(UI32)(UI64)

#define MY_SIGNED_UNSIGNED_INTEGER_SEQ    MY_SIGNED_INTEGER_SEQ MY_UNSIGNED_INTEGER_SEQ
#define MY_SIGNED_UNSIGNED_INTEGER_SUFFIX_SEQ    MY_SIGNED_INTEGER_SUFFIX_SEQ MY_UNSIGNED_INTEGER_SUFFIX_SEQ

#define MY_FLOAT_SEQ    (float32)(float64)
#define MY_FLOAT_SUFFIX_SEQ    (F32)(F64)

#define MY_BASIC_NUMERIC_TYPES_SEQ    MY_SIGNED_UNSIGNED_INTEGER_SEQ MY_FLOAT_SEQ
#define MY_BASIC_NUMERIC_TYPES_SUFFIX_SEQ    MY_SIGNED_UNSIGNED_INTEGER_SUFFIX_SEQ MY_FLOAT_SUFFIX_SEQ


#define MY_SEQ_OF_TYPES    MY_BASIC_NUMERIC_TYPES_SEQ
#define MY_SEQ_OF_SUFFICES    MY_BASIC_NUMERIC_TYPES_SUFFIX_SEQ

#define BOOST_PP_ITERATION_LIMITS (0, BOOST_PP_SEQ_SIZE(MY_SEQ_OF_TYPES) - 1)
#include BOOST_PP_ITERATE()

#undef MY_SEQ_OF_TYPES
#undef MY_SEQ_OF_SUFFICES

#endif

MyPointTypeImpl.h:

#include <boost/preprocessor/seq/elem.hpp>

#define n BOOST_PP_ITERATION()
#define PASTER(x,y) x ## y
#define EVALUATOR(x,y)  PASTER(x,y)
#define CONCATEVALUATED(x, y) EVALUATOR(x, y)

#define TYPE BOOST_PP_SEQ_ELEM(n, MY_SEQ_OF_TYPES)
#define SUFFIX BOOST_PP_SEQ_ELEM(n, MY_SEQ_OF_SUFFICES)

#define ADDSUFFIX(cls) CONCATEVALUATED(cls, SUFFIX)

struct ADDSUFFIX(Point)
{
  TYPE X;
  TYPE Y;
};

#undef n

MyPointTypes.cpp:

#define BOOST_PP_FILENAME_1 "MyPointTypeImpl.h"
#include "MyPointTypes.h"

Это определит типы:

PointI8, PointI16, PointI32, PointI64, 
PointUI8, PointUI16, PointUI32, PointUI64, 
PointF32, PointF64

Вообразите тогда вместо структуры C ++ тип значения C ++ / CLI, т.е.

public value class Point 

Затем мы эффективно создали точечные типы всех основных числовых типов для использования в .NET, например. C #.

1 голос
/ 08 февраля 2010

Старые (до шаблона) версии компиляторов C ++ часто имели заголовки <generic.h> для подобных вещей. Я искал бы старые версии g ++ для этого. Это было до моего времени, поэтому я не знаю, подойдет ли вам это или нет.

В качестве альтернативы, что-то вроде

#define TYPE short
#define TYPES I16
#include "Point.def"
#undef TYPE
#undef TYPES
#define TYPE int
#define TYPES I32
#include "Point.def"

также может помочь вам.

Или, очевидно, внешний генератор кода (в awk, perl, C ++ и т. Д.). Это может быть лучшим решением.

0 голосов
/ 19 августа 2010

Это кажется старым вопросом, но .... Я думаю, что проще сделать это только со стандартным макропроцессором (CPP)

#define STRUCT_POINT( P_TYPE ) \
struct Point##_##P_TYPE        \
{                              \
   P_TYPE X;                   \
   P_TYPE Y;                   \
                               \
};

#define CREATE_STRUCT_POINTS \
  STRUCT_POINT( short    )     \
  STRUCT_POINT( int      )     \
  STRUCT_POINT( unsigned )     \
  STRUCT_POINT( float    )     \
  STRUCT_POINT( double   )

CREATE_STRUCT_POINTS

#undef CREATE_STRUCT_POINTS
#undef STRUCT_POINT

Или, может быть, это изменение (следуя «спецификациям»)

#define STRUCT_POINT( P_TYPE, P_TYPE_ALIAS ) \
struct Point##P_TYPE_ALIAS     \
{                              \
   P_TYPE X;                   \
   P_TYPE Y;                   \
                               \
};

#define CREATE_STRUCT_POINTS \
  STRUCT_POINT( short    ,  I16  )     \
  STRUCT_POINT( int      ,  I32  )     \
  STRUCT_POINT( unsigned ,  U32  )     \
  STRUCT_POINT( float    ,  F32  )     \
  STRUCT_POINT( double   ,  F64  )

CREATE_STRUCT_POINTS

#undef CREATE_STRUCT_POINTS
#undef STRUCT_POINT
...