زيادة مكتبة المعالج مسبقا لتوليد مجموعة من الأنواع بناء على قائمة الأنواع الأساسية مثل Pointi32، PointF32 وما إلى ذلك في C ++ / CLI
-
19-09-2019 - |
سؤال
أحاول معرفة كيفية استخدام مكتبة Bost.Preprocessor http://www.boost.org/doc/libs/release/libs/preprocessor. لإشعال نوع "عام" لأنواع محددة مختلفة. أدناه سأطلب من هذا مثال فئة نقطة بسيطة. منح:
struct Point##TYPE_SUFFIX_NAME
{
TYPE X;
TYPE Y;
// Other code
};
أريد أن تولد هذا النوع لأنواع بيانات أساسية مختلفة (POD) على سبيل المثال:
PointF32, PointF64, PointI32 etc.
حيث pointf32 سيكون:
struct PointF32
{
float X;
float Y;
};
وهذا هو، بناء على قائمة الأنواع:
short, int, long, float, double etc.
أريد أن "تكشف" النوع أعلاه لهذه. ويفضل أن يكون تعريف "القالب" في ملف متضمن منفصل وليس ككائن ماكرو، للسماح بتصحيح الأخطاء أسهل.
ملاحظة: أنا غير مهتم بسمع قوالب C ++. أنا أعرف كيفية استخدام القوالب. ولكن هذه ليست مفيدة في حالتي. على سبيل المثال، تخيل أن تستخدم هذه الأنواع من .NET في C #، ولكن يتم إنشاؤها في C ++ / CLI. لذا يرجى التمسك بالسؤال.
المشكلة، بالطبع، ينبع من عدم وجود دعم القوالب في .NET وبسبب الأجواء لا تكون مناسبة لحل مشكلتي.
المحلول 3
بناء على إجابة Benoît لقد وصلت إلى الإجابة التالية. تتكون الجواب من ثلاثة ملفات:
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 IE:
public value class Point
ثم ننشئنا بشكل فعال أنواع نقطة من جميع الأنواع الرقمية الأساسية لاستخدامها في .NET على سبيل المثال C #.
نصائح أخرى
عمر او قديم (ما قبل القالب) إصدارات مترجم 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 ++، أيا كان). هذا يمكن أن يكون الحل الأفضل.
الكود التالي هو غير مختبر ولكن يجب أن تكون بداية جيدة لجعل ما تريد أن يحدث.
في my_sperures.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
وفي craise_my_sultrure.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
يبدو أن هذا سؤال قديم ولكن .... أعتقد أنه من الأسهل القيام بذلك فقط مع macropropcessor القياسية (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