2014-10-02 9 views
45

A seguito della mia risposta a this question, sia in C++ 11 e C++ 14:La specifica di `bsearch` in C++ 11 e C++ 14 è difettosa?

[C++11, C++14: 25.5/2]: I contenuti sono gli stessi della libreria standard C intestazione <stdlib.h> con le seguenti eccezioni:

[C++11, C++14: 25.5/3]: La firma della funzione:

bsearch(const void *, const void *, size_t, size_t, 
     int (*)(const void *, const void *)); 

è sostituito dai due dichiarazioni:

extern "C" void *bsearch(const void *key, const void *base, 
         size_t nmemb, size_t size, 
         int (*compar)(const void *, const void *)); 

extern "C++" void *bsearch(const void *key, const void *base, 
          size_t nmemb, size_t size, 
          int (*compar)(const void *, const void *)); 

entrambi con lo stesso comportamento della dichiarazione originale.

Tuttavia,

[C++11, C++14: 7.5/5]: Se due dichiarazioni dichiarano funzioni con lo stesso nome e il parametro di tipo-list (8.3.5) di essere membri della stessa namespace o dichiarare oggetti con lo stesso nome essere membri dello stesso namespace e le dichiarazioni danno i nomi di collegamenti linguistici diversi, il programma è mal formato; non è richiesta alcuna diagnostica se le dichiarazioni sono visualizzate in diverse unità di traduzione. [..]

È un difetto?

+0

La risposta dipende da queste due funzioni che hanno gli stessi argomenti oppure no. Se il collegamento è parte del tipo, 'compar' ha un tipo diverso in entrambi gli esempi ... anche se se lo è, voglio un modo semplice per dichiararlo per i tipi, e non ne sono a conoscenza. – Deduplicator

+0

@Deduplicator In C++ standard, è possibile utilizzare alias di modelli. 'template using CxxFunc = R (T ...); extern "C" {template using CFunc = R (T ...); } '. Dichiara 'compar' come' CFunc 'e' CxxFunc <...> '.La maggior parte delle implementazioni lo rifiuta perché non consentono i modelli nei blocchi "extern" C "', ma è perfettamente valido. La restrizione è che un template non può avere il link "extern" C "', non che un template non possa apparire in un blocco "extern" C "'. Un alias del modello non ha collegamenti linguistici, quindi va bene. – hvd

+1

È lo stesso modo in C++ 98 25.4/3 (e 25.4/4 per 'qsort') – Cubbi

risposta

49

Ma l'elenco dei tipi di parametri non è lo stesso. In uno, compar è un puntatore a una funzione con collegamento di linguaggio "C", nell'altro, è un puntatore a una funzione con collegamento di linguaggio "C++".

C++ 11, 7.5 specifica:

1 ... Due tipi di funzione con lingua diversa legami sono tipi distinti anche se sono altrimenti identici.

4 In un cinematismo-specifica , il legame lingua specificata vale per la funzione tipi di tutti dichiaratori funzione, nomi di funzioni con linkage esterno, e le variabili il parametro esterno linkage espressa entro il sollevatore-specifica . [Esempio:

extern "C" void f1(void(*pf)(int)); 
// the name f1 and its function type have C language 
// linkage; pf is a pointer to a C function 

L'incongruenza apparente tra 7,5/1 e 7,5/5 viene risolto quando rendersi conto che 1 parla funzione tipi, mentre 5 indirizzi funzionano nomi.

+0

C'è un modo semplice per dichiarare che il primo fp ha C++ e il secondo C linkage, per una funzione che prevede due funzioni- puntatori? – Deduplicator

+0

@Deduplicator Utilizzare un 'typedef' per il parametro che differisce dal collegamento linguistico della funzione contenuta. – Angew

+4

Non sembra però che clang ++ o g ++ li considerino diversi. http://coliru.stacked-crooked.com/a/ceb69c605e32832d – Deduplicator