C中C++中的模板

Templates from C++ in C

本文关键字:C++      更新时间:2023-10-16


我正在尝试从C中的C++标准库中重新创建一些类。例如,std::pair类
为了模仿模板,我当然使用了宏。以下是它的外观示例:

#define _TEMPLATE_PAIR_STRUCT(T1, T2, TNAME, STRNAME) 
typedef struct {                                  
    T1* first;                                    
    T2* second;                                   
} STRNAME;
#define _TEMPLATE_PAIR_NEW(T1, T2, TNAME, STRNAME) 
    STRNAME* TNAME##_new()                         
    {                                              
        STRNAME *new = malloc(sizeof( STRNAME ));  
        new->first = malloc(sizeof(T1));           
        new->second = malloc(sizeof(T2));          
        return new;                                
    }

如果我试图在多个源文件中使用这种结构,我必须多次生成代码。这显然导致了一个错误。

有没有办法解决这个问题,这样我就可以在C中使用这些"模板"了?

正如其他人所说,有几件事需要记住,主要是确保只有一个函数定义。

我不是特别喜欢这个解决方案,但它在这里。

一个标头来统治所有(pair.h(

#ifndef TEMPLATE_PAIR
#define TEMPLATE_PAIR
#include <stdlib.h>
#define PAIR_NAME( T1, T2 ) T1##T2##NAME
#define PAIR_PTR_NAME( T1, T2 ) T1##T2##PTR_NAME
#define PAIR_CREATE( T1, T2) MAKE##T1##T2
#define PAIR_PTR_CREATE( T1, T2) MAKE_PTR##T1##T2
#define PAIR_PTR_FREE(T1, T2) FREE##T1##T2
#define PAIR_DEFINITION( T1, T2) 
    typedef struct { 
    T1 first; 
    T2 second ; 
    } PAIR_NAME(T1, T2)
#define PAIR_PTR_DEFINITION( T1, T2) 
    typedef struct { 
    T1* first; 
    T2* second ; 
    } PAIR_PTR_NAME(T1, T2)
#define MAKE_PAIR_DECLARE(T1, T2) PAIR_NAME(T1, T2) PAIR_CREATE(T1, T2) ( const T1& V1, const T2& V2 )
#define MAKE_PAIR_PTR_DECLARE(T1, T2) PAIR_PTR_NAME(T1, T2) PAIR_PTR_CREATE(T1, T2) ( const T1& V1, const T2& V2 )
#define PAIR_PTR_FREE_DECLARE(T1, T2) void PAIR_PTR_FREE(T1, T2) ( PAIR_PTR_NAME(T1, T2) & Pair )
#define MAKE_PAIR_SIGNATURE(T1, T2) PAIR_NAME(T1, T2) PAIR_CREATE(T1, T2) ( const T1& V1, const T2& V2 )
#define MAKE_PAIR_PTR_SIGNATURE(T1, T2) PAIR_PTR_NAME(T1, T2) PAIR_PTR_CREATE(T1, T2) ( const T1& V1, const T2& V2 )
#define FREE_PAIR_PTR_SIGNATURE(T1, T2) void PAIR_PTR_FREE(T1, T2) ( PAIR_PTR_NAME(T1, T2) & Pair )
#define MAKE_PAIR_DEFINE( T1, T2 ) 
    MAKE_PAIR_SIGNATURE(T1, T2) { 
        PAIR_NAME(T1, T2) pair; 
        pair.first = V1; 
        pair.second = V2; 
        return pair; 
        }
#define MAKE_PAIR_PTR_DEFINE( T1, T2 ) 
    MAKE_PAIR_PTR_SIGNATURE(T1, T2) { 
        PAIR_PTR_NAME(T1, T2) pair; 
        pair.first = malloc( sizeof(T1) ); 
        if ( pair.first != 0 ) *(pair.first) = V1; 
        pair.second = malloc( sizeof( T2) ) ; 
        if ( pair.second != 0 ) *(pair.second) = V2; 
        return pair; 
        }
#define PAIR_PTR_FREE_DEFINE( T1, T2 ) 
    FREE_PAIR_PTR_SIGNATURE(T1, T2) { 
    free( Pair.first ); 
    free( Pair.second ); 
    }
#endif

一个标题带来他们所有(defs.h(:

#ifndef DEFS_HEADER
#define DEFS_HEADER
#include "pair.h"
typedef int* pInt;
PAIR_DEFINITION( int, int );
PAIR_DEFINITION( int, double );
PAIR_DEFINITION( double, double );
PAIR_DEFINITION( pInt, pInt );
PAIR_DEFINITION( float, int );
PAIR_PTR_DEFINITION( int, int );
MAKE_PAIR_DECLARE( int, int );
MAKE_PAIR_DECLARE( int, double );
MAKE_PAIR_DECLARE( double, double );
MAKE_PAIR_DECLARE( pInt, pInt );
MAKE_PAIR_DECLARE( float, int );
MAKE_PAIR_PTR_DECLARE( int, int );
PAIR_PTR_FREE_DECLARE( int, int );
#endif

在黑暗中束缚他们(impl.c(:

#include "defs.h"
MAKE_PAIR_DEFINE( int, int );
MAKE_PAIR_DEFINE( int, double );
MAKE_PAIR_DEFINE( double, double );
MAKE_PAIR_DEFINE( pInt, pInt );
// manual "instantiation"
MAKE_PAIR_SIGNATURE( float, int )
{
    PAIR_NAME( float, int ) local;
    local.first = V1;
    local.second = V2;
    return local;
}
MAKE_PAIR_PTR_DEFINE( int, int );
PAIR_PTR_FREE_DEFINE( int, int );

在阴影所在的主之地:

#include "defs.h"

int main(void)
{
    PAIR_NAME(int, int) myPairInts;
    PAIR_NAME( double, double) myPairDoubles;
    PAIR_NAME( pInt, pInt) myPairPointers;
    PAIR_NAME( float, int) myPairOther;
    PAIR_PTR_NAME( int, int ) pairPtr;

    myPairInts = PAIR_CREATE( int, int ) (1, 2);
    myPairDoubles = PAIR_CREATE( double, double ) (5, 6.5);
    myPairPointers = PAIR_CREATE( pInt, pInt) ( 0, 0 );
    myPairOther = PAIR_CREATE( float, int) (1, 1);
    pairPtr = PAIR_PTR_CREATE(int, int) (1, 2 );
    PAIR_PTR_FREE(int, int) (pairPtr );

    return 0;
}

PAIR_NAME创建一个包含值的结构,PAIR_PTR_NAME包含指向值的指针。CCD_ 3和CCD_。

您需要在"impl.c"中定义所有必要的组合。任何编译单元都可以#include "defs.h"并使用这些对。

编辑-问题解答:

  1. "当我在库或类似的东西中使用一次,然后在同时使用该库和对"模板"的程序中再次使用时,这不会引起麻烦吗?">

"pair.h"只包含宏,可以在任何库或程序中安全使用。

重要的是,同一个函数不能定义两次。我也不会两次定义相同的结构。

不过,您可以执行以下操作:-将pair.h、defs.h和impl.c如上所述,并将它们构建到库中(添加任何必要的__declspec(dllexport)__declspec(dllimport(-然后可以使用#include pair.hdefs.h,并使用程序中定义的对-如果你想使用新的对,比如说对于(float, float),你需要添加一个新的defs_my_program.h和一个新impl_my_program.c来声明和定义这些新的对。defs_my_program.h报头可以与库提供的defs.h报头一起被包括。

对于每一对,您仍然可以得到一个声明和一个定义。唯一的"缺点"是你不能真正(安全地(在运行中使用对,它们需要集中。

  1. "您选择类型和函数名称的方式确实会带来一些问题。你把一对有两个值的和一个有两个指针的分开。对于一个指针和一个值的对,以及一个值和一个指针的对,您还需要专门化。所以我已经有4箱了。将此用于三元组甚至更高的元组,我将不得不实现2^n种情况。">

首先,你要求的是std::pair,而不是一个傻瓜。

注意,std::pair相当于PAIR_NAME,不存在分配动态内存的std::pair

如果您不需要自动使用malloc,则不需要任何新的专业化。使用pInt的示例显示,您可以创建(int, int*)(int*, int)pair。只是指针的需要来自pair之外。

如果您真的想要一个(int, int*)pair,它可以自动为int*分配内存,那么如果您确实需要它,您必须自己添加它。我希望你不会。

对于值的元组,不太理想的解决方案可能是使用pairpair和另一个元素。这将为您提供一个包含三个元素的结构。这样的事情可能可以通过宏观魔法来实现,减少你担心的指数增长。

多次声明结构不是问题。

多次定义函数是个问题。如果您将函数设置为静态,那么它将成为每个文件一次的问题。即使在C++中,有时人们也会显式地实例化模板。您可以拥有一个具有所有新功能的文件。

如果您想要一个自动解决方案,那么您需要了解C++编译器是如何实例化模板的。这是一种很久以前就使用过的方法。

  • 编译和链接您的代码而不使用PAIR_NEW
  • 您将获得未定义的_new((函数
  • 运行一个脚本,该脚本使用正确的PAIR_NEW((宏调用生成一个C文件,以定义未定义的符号
  • 编译这个新文件,并重新链接包括新文件在内的项目

从这个问题中抽象出来,如果这是一个好主意,那么在实现中会出现一些错误。

  • 永远不要在宏中隐藏PAIR_CREATE0,这完全违背了使用它的地方的视觉预期
  • 除了在C++中,没有接收参数的函数应该在CCD_ 32内具有CCD_
  • 保留以下划线和大写字母开头的名称用于所有上下文中的C实现。选择更好的命名公约
  • 除了在C++中,CCD_ 33函数不会初始化数据,这也是一个糟糕的命名约定
  • 您正在使用标识符new作为局部变量,如果您希望有一天能将其连接到某个C++
  • 函数的宏应该分为三部分:(1(将函数名称插在一起的命名约定,(2( inline定义和(3(外部"实例化"您可以在一个编译单元中生成函数符号
相关文章:
  • 没有找到相关文章