読者です 読者をやめる 読者になる 読者になる

とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

C99, C++ で使える using マクロ書いた

プログラム言語C C++ Preprocessor

C# なんかである using をマクロ使って実装してみました。とはいっても,C++ は RAII があるので,主なターゲットは C99 です。古いC言語では for 内で変数の宣言ができないので対応していません。
あ,using ブロック内で return するとリソースリーク起きますね。これはC言語ではどうしようもない問題です。すみませぬ。
こんな感じで使います。クライアントコード:

#include<stdlib.h>
#include<stdio.h>
#include<sscrisk/preprocessor/using.hpp>

#define using SSCRISK_PP_USING
int main()
{
 // void* const p = malloc(sizeof(int));
 using(p, malloc,(sizeof(int)))
 {
  int* const q = (int*)p;
  *q = 'a';
  putchar(*q);
 }
 // free(p)

 // FILE* const fp = fopen("text.txt", "r");
 using(fp, fopen,("text.txt", "r"))
 {
  int const ch = fgetc(fp);
  putchar(ch);
 }
 // fclose(fp);
}
#undef using

実行結果(fopenに失敗したケース):

a

ライブラリ:

#if !defined(SSCRISK_PREPROCESSOR_USING_HPP)
#define SSCRISK_PREPROCESSOR_USING_HPP
#if defined(_MSC_VER) && _MSC_VER >= 1020
#pragma once
#endif

// using.hpp

#define SSCRISK_PP_DEFINE_USING(return_type, release_func, id, func_call) \
 for(return_type sscrisk_##id##_dummy_cant_use = func_call; \
  sscrisk_##id##_dummy_cant_use;) \
  for(return_type const id = sscrisk_##id##_dummy_cant_use; \
   sscrisk_##id##_dummy_cant_use; release_func(sscrisk_##id##_dummy_cant_use),\
   sscrisk_##id##_dummy_cant_use = 0)

#define SSCRISK_PP_USING_malloc(a, b) \
 SSCRISK_PP_DEFINE_USING(void*, free, a, b)
#define SSCRISK_PP_USING_fopen(a, b) \
 SSCRISK_PP_DEFINE_USING(FILE*, fclose, a, b)

#define SSCRISK_PP_USING(id, get_func, param) \
 SSCRISK_PP_USING_##get_func(id, get_func param)

#endif