他の人が言ったように、心に留めておくべきことがいくつかあります。主に、関数定義が 1 つだけであることを確認してください。
私はこのソリューションが特に好きではありませんが、ここにあります。
それらすべてを支配する 1 つのヘッダー (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
それらすべてをもたらす 1 つのヘッダー (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
ポインターを含みます。PAIR_CREATE
値をPAIR_PTR_CREATE
作成し、ペア内にデータを入力します。
「impl.c」で必要なすべての組み合わせを定義する必要があります。どのコンパイル単位でも#include "defs.h"
ペアを使用できます。
編集 - 質問への回答:
- 「これをライブラリなどで一度使用し、そのライブラリとペアの「テンプレート」の両方を使用するプログラムでもう一度使用すると、問題が発生しませんか?」
「pair.h」にはマクロのみが含まれており、どのライブラリやプログラムでも安全に使用できます。
重要なのは、同じ関数を 2 回定義しないことです。同じ構造を 2 回定義することもありません。
ただし、次のことを行うことができます: -上記のようにpair.h、defs.h、およびimpl.cを取得し、それらをライブラリに構築します(必要な__declspec(dllexport)
およびを追加し__declspec(dllimport
ます)-その後#include pair.h
、defs.h
そこで定義されたペアをプログラムで使用できます- 新しいペアを使用したい場合は、これらの新しいペアを宣言および定義するためにnewと(float, float)
new を追加する必要があるとします。ヘッダーは、ライブラリが提供するヘッダーと一緒に含めることができます。defs_my_program.h
impl_my_program.c
defs_my_program.h
defs.h
ペアごとに 1 つの宣言と 1 つの定義を引き続き取得します。唯一の「欠点」は、ペアをオンザフライで実際に (安全に) 使用できないことです。それらは集中化する必要があります。
- 「型と関数名を選択した方法には、いくつかの問題があります。2 つの値を持つペアと 2 つのポインターを持つペアを分割します。また、1 つのポインターと 1 つの値を持つペアの特殊化も必要です。 1 つの値と 1 つのポインターを持つペアの場合。つまり、既に 4 つのケースのペアがあることになります。これをトリプレットまたはそれ以上のタプルに使用すると、2^n ケースを実装する必要があります。」
まず第一に、あなたはタプルを求めたのstd::pair
ではなく、求めました。
std::pair
は と同等であることに注意してください。動的メモリを割り当てるPAIR_NAME
ものはありません。std::pair
を自動的に使用する必要がない場合は、新しい専門化は必要ありませんmalloc
。の例は、またはpInt
の を作成できることを示しています。ポインターの値が の外部から取得される必要があるだけです。pair
(int, int*)
(int*, int)
pair
にメモリを自動的に割り当てるpair
ofが本当に必要な場合は、実際に必要な場合は自分で追加する必要があります。そうしないことを願っています。(int, int*)
int*
pair
値のタプルの場合、 apair
と別の要素の aを使用するのは、あまり最適な解決策ではない可能性があります。これにより、3 つの要素を含む構造が得られます。そのようなことは、おそらくマクロマジックを介して行うことができ、心配している指数関数的な成長を削減できます.