Tidak, ini disebut kelebihan beban dan ini bukan fitur yang dimiliki C. Anda sebaiknya membuat fungsi berbeda untuk menangani hal ini.
Anda dapat melakukannya dengan semua jenis sihir C (Anda bisa melakukan apa saja dengan cukup sihir C), namun kode yang dihasilkan mungkin sangat jelek sehingga tidak dapat dipelihara: -)
Misalnya, C11 memperkenalkan pilihan umum, dengan ekspresi utama _Generic
, dan ini memungkinkan Anda memanggil fungsi berbeda berdasarkan tipe argumen masukan. Sebenarnya fungsinya lebih dari itu, tapi itulah aspek yang Anda minati, berdasarkan pertanyaan Anda.
Misalnya, Anda mendefinisikan dua fungsi sebagai berikut:
int diffi (int a, int b) { return a - b; }
double diffd (double a, double b) { return a - b; }
Biasanya, Anda harus memutuskan mana yang akan dipanggil berdasarkan jenis masukan Anda. Fitur pemilihan umum C11 memungkinkan Anda melakukan ini:
#define diff(a,b) \
_Generic((a), \
double: diffd, \
int: diffi, \
default: diffX \
)(a,b)
Dan apa yang dilakukannya pada dasarnya adalah menemukan makro diff(x,y)
di kode sumber:
- menentukan jenis ekspresi
(a)
tanpa mengevaluasinya;
- menyuntikkan ke aliran sumber token yang cocok dengan jenis tersebut (atau default jika tidak ditemukan kecocokan);
- menyuntikkan ke aliran sumber teks
(a,b)
di akhir.
Jadi, jika file sumber Anda berisi baris:
x = diff (1, 2);
y = diff (1.0, 2);
ini akan diterjemahkan ke dalam:
x = diffi (1 , 2);
y = diffd (1.0, 2);
memberi Anda kelebihan beban yang efektif.
Itu kasus yang cukup mudah karena hanya bergantung pada tipe argumen pertama - Anda akan melihat lubang di sana jika Anda mencoba melakukannya:
z = diff (1, 2.0);
di mana tipe argumen pertama adalah int
sehingga Anda akan mendapatkan:
z = diffi (1, 2.0);
yang sebenarnya bukan hal yang ingin Anda lakukan. Di sinilah kompleksitas muncul karena Anda harus mencakup empat kemungkinan: {int/int, int/double, double/int, double/double}
dan ini menjadi lebih kompleks berdasarkan jumlah argumen dan kemungkinan tipe untuk setiap argumen.
Namun, kasus lengkap Anda dapat dilakukan dengan penggunaan default yang bijaksana dan pilihan umum yang disarangkan, seperti:
#define diff(a,b) \
_Generic((a), \
double: diffd, \
default: _Generic((b), \
double: diffd, \
default: diffi \
) \
)(a,b)
dan ini dapat dibaca sebagai:
- jika tipe
a
adalah double
, gunakan diffd
;
- sebaliknya, jika tipe
b
adalah double
, gunakan diffd
;
- jika tidak, gunakan
diffi
.
- jangan lupa untuk memasukkan argumennya juga.
Program lengkap berikut (dikompilasi dengan clang 3.0
) menunjukkan cara kerja fitur ini:
#include <stdio.h>
int diffi (int a, int b) {
printf ("diffi %d %d", a, b);
return a - b;
}
double diffd (double a, double b) {
printf ("diffd %f %f", a, b);
return a - b;
}
#define diff(a,b) \
_Generic((a), \
double: diffd, \
default: _Generic((b), \
double: diffd, \
default: diffi \
) \
)(a,b)
int main (void) {
int i; double d;
i = diff (1 , 2 ); printf (" --> %d\n", i);
d = diff (1.0, 2 ); printf (" --> %f\n", d);
d = diff (1 , 2.0); printf (" --> %f\n", d);
d = diff (1.0, 2.0); printf (" --> %f\n", d);
return 0;
}
Output dari program itu adalah:
diffi 1 2 --> -1
diffd 1.000000 2.000000 --> -1.000000
diffd 1.000000 2.000000 --> -1.000000
diffd 1.000000 2.000000 --> -1.000000
menunjukkan bahwa fungsi yang benar dipanggil untuk empat kemungkinan.
Faktanya, seperti rici tunjukkan dalam komentar, Anda dapat mengandalkan aturan promosi C, di mana menambahkan double
dan int
(dalam urutan apa pun) memberi Anda double
sementara menambahkan dua variabel int
memberi Anda int
:
#define diff(a,b) _Generic((a+b), double:diffd, default:diffi)(a,b)
person
paxdiablo
schedule
21.10.2014