C++ 03 consente di qualificare i parametri di funzione come const
, volatile
e/oi riferimenti di lvalue (&
).C++ 11: Riassunto su puntatori funzione const, riferimento volatile, di riferimento lvalue e riferimento a rvalore?
C++ 11 aggiunge uno di più: riferimenti di rvalue (&&
).
Inoltre, C++ consente di sovraccaricare le funzioni in base ai qualificatori dei loro parametri, in modo che venga selezionato il sovraccarico più appropriato quando si chiama la funzione.
Una funzione membro può essere pensata concettualmente come una funzione che accetta un parametro aggiuntivo, il cui tipo è un riferimento a un'istanza della classe di cui è membro. È possibile sovraccaricare una funzione membro in base ai qualificatori di questo 'parametro aggiuntivo' più o meno allo stesso modo di qualsiasi altro parametro. Ciò è espresso mettendo qualificazioni alla fine della firma funzione:
struct Foo
{
int& data(); // return a non-const reference if `this` is non-const
const int& data() const; // return a const reference if `this` is const
};
in C++ 03, const
e volatile
qualificatori sono possibili, e C++ 11 permette anche &
e &&
(&
potrebbe teoricamente stato permesso in C++ 03, ma non lo era).
Qualsiasi combinazione di qualificazione può essere utilizzato, con l'eccezione che &
e &&
sono mutuamente esclusivi, che rende per 2^2 = 4 possibilità in C++ 03 e 2^4-4 = 12 a C++ 11 .
Questo può essere un bel dolore quando si desidera lavorare con puntatori a funzione membro, perché non sono anche un po 'polimorfica in queste qualificazioni: le qualificazioni sul "this
tipo" di un puntatore a funzione membro passato come l'argomento deve corrispondere esattamente a quelli sul tipo del parametro che viene passato come. Anche il C++ non offre alcuna possibilità esplicita di astrarre i qualificatori. In C++ 03 questo era principalmente OK, perché dovresti scrivere una versione const
e una versione non-const
e nessuno si preoccupa di volatile
, ma nel caso patologico in C++ 11 (che non è così raro come è patologico) potresti dover scrivere manualmente fino a 12 sovraccarichi. Per funzione.
sono stato molto felice di scoprire che se si passa il tipo della classe racchiude come un parametro di template e trarre il tipo di un puntatore a funzione membro da esso, che const
e volatile
qualificazioni sono ammessi e propagate come ci si aspetterebbe :
template<typename Object>
struct Bar
{
typedef int (Object::*Sig)(int);
};
Bar<Baz>; // Sig will be `int (Baz::*)(int)`
Bar<const Baz>; // Sig will be `int (Baz::*)(int) const`
Bar<volatile Baz>; // Sig will be `int (Baz::*)(int) volatile`
Bar<const volatile Baz>; // Sig will be `int (Baz::*)(int) const volatile`
Questo è molto bello di dover scrivere tutti i casi manualmente.
Sfortunatamente, non sembra funzionare per &
e &&
.
GCC 4.7 dice:
error: forming pointer to reference type ‘Baz&&’
Ma non è troppo sorprendente, dal momento che GCC come di 4,7 non ha ancora il supporto per le qualificazioni di riferimento su this
.
ho anche provato con Clang 3.0, che ha tale supporto:
error: member pointer refers into non-class type 'Baz &&'
Oh, bene.
Sono corretto nel concludere che ciò non è possibile e che non è possibile astrarre su qualificatori di riferimento su "this type
" di puntatori funzione membro? Qualsiasi altra tecnica di astrazione su qualificatori (in particolare su this
) diversa dal caso specifico quando si passa il "this
tipo" come parametro del modello sarebbe anche apprezzata.
(Vale la pena sottolineare che se C++ non distinguesse tra funzioni membro e funzioni normali, tutto sarebbe banale: si userebbe il parametro template come tipo di parametro della funzione (puntatore), e l'argomento del modello sarebbe passato così com'è, i qualificatori intatti, nessun pensiero aggiuntivo necessario.)
Con quale frequenza è necessario un comportamento diverso per tutte le possibili combinazioni di qualificatori? (O, del resto, anche due o tre combinazioni possibili?) –
Se sto provando a scrivere un'astrazione per oggetti simili a funzioni (nello spirito di std :: function ma non è la stessa cosa), allora la completezza è un obiettivo di design . Non posso davvero estrapolare o stimare (quanto a quanto frequentemente) ma so che ci ho già provato prima. – glaebhoerl