Pragma dalam mendefinisikan makro

99

Apakah ada cara untuk menyematkan pernyataan pragma di makro dengan pernyataan lain?

Saya mencoba mencapai sesuatu seperti:

#define DEFINE_DELETE_OBJECT(type)                      \
    void delete_ ## type_(int handle);                  \
    void delete_ ## type(int handle);                                                \
    #pragma weak delete_ ## type_ = delete_ ## type

Saya baik-baik saja dengan solusi boost (simpan untuk gelombang) jika ada.

Anycorn
sumber
5
Bisa dibilang itu bukan keduanya - #pragmas tidak ditentukan oleh standar C atau C ++.
Praprosesor adalah, meskipun subperintah tertentu yang diizinkan yang ingin dia jalankan tidak.
Anak anjing
@DeadMG: Ada banyak kesamaan antara C dan C ++. Sementara preprocessing umumnya umum, ada perbedaan besar dalam bagaimana preprocessing ditentukan tergantung pada standar bahasa yang digunakan (C89, C99, C ++, dan C ++ 0x FCD).
James McNellis
2
@ James McNellis: Hanya karena secara teknis, sebagian besar program C portabel ke C ++, tidak membuat fungsionalitas yang benar-benar umum, karena tidak ada programmer C ++ yang akan melakukan sebagian besar dari itu. Kedua bahasa tersebut sebenarnya tidak memiliki banyak kesamaan.
Anak anjing

Jawaban:

115

Jika Anda menggunakan c99 atau c ++ 0x ada operator pragma, digunakan sebagai

_Pragma("argument")

yang setara dengan

#pragma argument

kecuali itu dapat digunakan dalam makro (lihat bagian 6.10.9 dari standar c99, atau 16.9 dari draf komite akhir c ++ 0x)

Sebagai contoh,

#define STRINGIFY(a) #a
#define DEFINE_DELETE_OBJECT(type)                      \
    void delete_ ## type ## _(int handle);                  \
    void delete_ ## type(int handle);                   \
    _Pragma( STRINGIFY( weak delete_ ## type ## _ = delete_ ## type) )
DEFINE_DELETE_OBJECT(foo);

ketika dimasukkan ke dalam gcc -Ememberi

void delete_foo_(int handle); void delete_foo(int handle);
#pragma weak delete_foo_ = delete_foo
 ;
Scott Wales
sumber
32
Sebagai FYI: MSVC memiliki __pragma()operator preprocessor, yang sayangnya sedikit berbeda dari _Pragma()operator C99 (C99 menggunakan literal string, MSVC mengambil token yang tidak dalam string): msdn.microsoft.com/en-us/library/d9x1s805 .aspx
Michael Burr
15
@MichaelBurr MSVC selalu harus berbeda, bukan?
Thomas
5

Satu hal baik yang dapat Anda lakukan dengan _Pragma ("argumen") adalah menggunakannya untuk menangani beberapa masalah kompilator seperti

#ifdef _MSC_VER
#define DUMMY_PRAGMA _Pragma("argument")
#else
#define DUMMY_PRAGMA _Pragma("alt argument")
#endif
John Thomas
sumber
0

Tidak, tidak ada cara portabel untuk melakukan itu. Selain itu, tidak ada cara portabel untuk menggunakan #pragma sama sekali. Karenanya, banyak compiler C / C ++ yang menentukan metodenya sendiri untuk melakukan hal-hal yang mirip pragma, dan mereka sering kali dapat disematkan di makro, tetapi Anda memerlukan definisi makro yang berbeda pada setiap kompiler. Jika Anda bersedia menempuh jalur itu, Anda sering kali akhirnya melakukan hal-hal seperti ini:

#if defined(COMPILER_GCC)
#define Weak_b
#define Weak_e __attribute__((weak))
#elif defined(COMPILER_FOO)
#define Weak_b __Is_Weak
#define Weak_e
#endif

#define DEFINE_DELETE_OBJECT(type)                      \
    Weak_b void delete_ ## type_(int handle) Weak_e;    \
    Weak_b void delete_ ## type(int handle)  Weak_e;    

Jika tidak jelas Anda ingin mendefinisikan Weak_bdan Weak_esebagai konstruksi bracketing begin-and-end karena beberapa kompiler seperti GCC menambahkan atribut sebagai tambahan untuk tanda tangan tipe, dan beberapa, seperti MSC menambahkannya sebagai awalan (atau setidaknya melakukannya sekali, sudah bertahun-tahun sejak saya menggunakan MSC). Memiliki bracketing contruct memungkinkan Anda untuk menentukan sesuatu yang selalu berfungsi, bahkan jika Anda harus meneruskan seluruh tanda tangan tipe ke dalam konstruksi kompilator.

Tentu saja, jika Anda mencoba mem-porting ini ke kompiler tanpa atribut yang Anda inginkan, tidak ada yang dapat Anda lakukan selain membiarkan makro meluas dan berharap kode Anda tetap berjalan. Jika hanya memperingatkan atau mengoptimalkan pragma, ini mungkin terjadi. Dalam kasus lain, tidak terlalu banyak.

Oh, dan saya curiga Anda benar-benar perlu mendefinisikan Weak_b dan Weak_e sebagai makro yang mengambil parameter, tetapi saya tidak bersedia membaca dokumen tentang cara membuat definisi yang lemah hanya untuk contoh ini. Saya tinggalkan itu sebagai latihan untuk pembaca.

swestrup
sumber
-3

apakah ada cara untuk menyematkan pernyataan pragma di makro dengan pernyataan lain?

Tidak, Anda tidak dapat memasukkan pernyataan preprocessor ke dalam pernyataan preprocessor. Anda bisa, bagaimanapun, memasukkannya ke dalam sebuah inlinefungsi. Itu mengalahkan Clabelnya.

sbi
sumber
1
Apa gunanya memasukkannya ke dalam fungsi sebaris? Arahan preprocessor diproses sebelum apapun yang dapat mengenali suatu fungsi.
2
C99 memiliki inline, dan sebagian besar implementasi C89 memiliki beberapa variasi.
Chris Lutz
@ Chris Dengan asumsi komentar Anda ditujukan kepada saya - maksud Anda adalah - apa?
@Neil - Tidak, maaf. Saya mengarahkannya pada kalimat terakhir @ sbi.
Chris Lutz
1
@ Chris: Ah, begitu inlinejuga hal lain yang dipinjam C dari C ++! :)
sbi