Vale più di mille parole:
#include<string>
#include<iostream>
class SayWhat {
public:
SayWhat& operator[](const std::string& s) {
std::cout<<"here\n"; // To make sure we fail on function entry
std::cout<<s<<"\n";
return *this;
}
};
int main() {
SayWhat ohNo;
// ohNo[1]; // Does not compile. Logic prevails.
ohNo[0]; // you didn't! this compiles.
return 0;
}
Il compilatore non si lamenta quando passa il numero 0 all'operatore parentesi quadra accettando una stringa. Invece, questo compila e fallisce prima dell'entrata nel metodo con:
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Per riferimento:
> g++ -std=c++17 -O3 -Wall -Werror -pedantic test.cpp -o test && ./test
> g++ --version
gcc version 7.3.1 20180303 (Red Hat 7.3.1-5) (GCC)
La mia ipotesi
Il compilatore utilizza implicitamente il file std::string(0)
costruttore per inserire il metodo, che produce lo stesso problema (google l'errore sopra) senza motivo.
Domanda
Esiste un modo per risolvere questo problema dal lato della classe, quindi l'utente dell'API non lo sente e l'errore viene rilevato al momento della compilazione?
Cioè, aggiungendo un sovraccarico
void operator[](size_t t) {
throw std::runtime_error("don't");
}
non è una buona soluzione.
operator[]()
che accetta un int
argomento e non definirlo.