加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

我可以在C中获得“宏多态性”吗?

发布时间:2020-12-16 10:36:36 所属栏目:百科 来源:网络整理
导读:我所追求的多态性类型是这样的: 假设我有一个名为draw()的宏,我有2个结构,一个叫做圆圈,另一个叫做方形.有可能以某种方式做这样的事情: #define draw() // can I get the text that's behind the macro?//then maybe,with _Generic achieve this?void draw
我所追求的多态性类型是这样的:

假设我有一个名为draw()的宏,我有2个结构,一个叫做圆圈,另一个叫做方形.有可能以某种方式做这样的事情:

#define draw() // can I get the text that's behind the macro?
//then maybe,with _Generic achieve this?


void draw_circle(struct circle);
void draw_square(struct square);

struct circle c;
struct square s;

c.draw();//draw is a macro. this time it is supposed to expand to draw_circle(c);
s.draw();//supposed to expand to draw_square(s);

EDIT_1:在阅读完答案之后,这是我到目前为止所做的.

//raw_array.h
#pragma once
#include <stdint.h>
#include <stdlib.h>

#define byte uint8_t
#define _GET_OVERRIDE(_1,_2,_3,NAME,...) NAME
/*#define init_impl(...) _GET_OVERRIDE(__VA_ARGS__,
    init_impl3,init_impl2,init_impl1)(__VA_ARGS__)
#define init( name,... ) (raw_array * (name); init_impl( (name),__VA_ARGS__))*/

#define array_init_impl(...) _GET_OVERRIDE(__VA_ARGS__,init_array_impl3,init_array_impl2,init_array_impl1)(__VA_ARGS__)

///<summary>creates a variable of type raw_array with name as an identifier,and initializes based on the parameters</summary>
#define RAW_ARRAY( name,... ) raw_array (name); array_init_impl( (&name),__VA_ARGS__)
typedef struct indexable_memory_block_struct
{
    raw_array * _self;
    byte * bytes;
    size_t element_size;
    size_t number_of_elements;

} raw_array;

///<summary>starts the an empty raw_array. only element_size is set.</summary>
///<param name=r_arr>the raw_array to be initialized</param>
///<param name=element_size>the size of the elements in this raw_array</param>
void init_impl1 ( raw_array * r_arr,size_t element_size )
{
    r_arr = malloc ( sizeof ( raw_array ) );
    r_arr->element_size = element_size;
    r_arr->number_of_elements = 0;
    r_arr->bytes = NULL;
    r_arr->_self = r_arr;
}

///<summary>
///starts the raw_array an empty. byte with its bytes allocated
///to their default value (0).
///</summary>
///<param name=r_arr>the raw_array to be initialized</param>
///<param name=element_size>the size of the elements in this raw_array</param>
///<param name=number_of_elements>the number of elements in the array</param>
void init_impl2 ( raw_array * r_arr,size_t element_size,size_t number_of_elements )
{
    r_arr = malloc ( sizeof ( raw_array ) );
    r_arr->element_size = element_size;
    r_arr->number_of_elements = number_of_elements;
    r_arr->bytes = calloc ( number_of_elements,element_size );
    r_arr->_self = r_arr;
}

///<summary>
///starts the raw_array copying its contents from a normal array.
///</summary>
///<param name=r_arr>the raw_array to be initialized</param>
///<param name=arr>the normal C array whose contents will be copied to this raw_array</param>
///<param name=element_size>the size of the elements in this    raw_array</param>
///<param name=number_of_elements>the number of elements in the array</param>
void init_impl3 ( raw_array * r_arr,const void * const arr,size_t size_of_element,size_t number_of_elements )
{
    r_arr->bytes = malloc ( size_of_element * number_of_elements );

    memcpy ( r_arr->bytes,arr,size_of_element * number_of_elements );
    r_arr->element_size = size_of_element;
    r_arr->number_of_elements = number_of_elements;
    r_arr->_self = r_arr;
}

还有其他部分,但这些是目前移植到这种新语法的部分.现在主要:

int main ( int argc,char * argv[] )
{
    int data[30];

    //line bellow has a compilation error: *expected a ')'*
    init ( r_arr,data,sizeof ( int ),30 );
}

什么意思预期’)’
你们可以查看宏语法吗?
关于_Generic,我今天学到了它,如果它有用的话,我肯定会使用它.

EDIT_2:发现严重错误,将修复它并再次编辑. Visual Studio正在更新(12GB ……)所以我目前无法构建任何东西. [迷你编辑]:我猜我至少修正了粗错误. [迷你编辑]我的代码中另一个非常奇怪的错误,我将名称标记字符串化,是吗?!现在纠正了.

EDIT_3:已经睡觉并且VS再次运行,我修复了宏,将编辑它们并注释掉错误的代码.现在我需要circle.draw()行为……任何想法?

解决方法

除了@LirooPierre的方法,你还可以使用C11 Generics.是的你没听错,C现在有仿制药.

考虑这个例子:

#include <stdio.h>
#define draw(X) _Generic((X),
        struct circle: draw_circle,
        struct square: draw_square 
        )(X)

struct circle{};
struct square{};

void draw_circle(struct circle a)
{
    printf("Drawing a circlen");
}
void draw_square(struct square a)
{
    printf("Drawing a squaren");
}

int main(void)
{
    struct square a;
    draw(a);  // "Drawing a square"
}

但即使它应该是便携式的,但遗憾的是它不是. M $编译器没有实现它们,但是clang和gcc这样做.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读