Domanda

Qualche tempo fa sono stato confuso dal seguente comportamento di alcuni codice quando ho voluto scrivere un tratto is_callable<F, Args...>. risoluzione di sovraccarico non richiamare le funzioni che accettano gli argomenti da ref non edificati, giusto? Perché non si rifiuta di seguito poiché il costruttore vuole un Test&? Mi aspettavo che prendere f(int)!

struct Test {
  Test() { }

  // I want Test not be copyable from rvalues!
  Test(Test&) { }

  // But it's convertible to int
  operator int() { return 0; }
};

void f(int) { }
void f(Test) { }

struct WorksFine { };
struct Slurper { Slurper(WorksFine&) { } };
struct Eater { Eater(WorksFine) { } };

void g(Slurper) { }
void g(Eater) { } // chooses this, as expected

int main() {
  // Error, why?
  f(Test());

  // But this works, why?
  g(WorksFine());
}

Il messaggio di errore è

m.cpp: In function 'int main()':
m.cpp:33:11: error: no matching function for call to 'Test::Test(Test)'
m.cpp:5:3: note: candidates are: Test::Test(Test&)
m.cpp:2:3: note:                 Test::Test()
m.cpp:33:11: error:   initializing argument 1 of 'void f(Test)'

Si può spiegare il motivo per cui si lavora, ma l'altro non lo fa?

È stato utile?

Soluzione

risoluzione sovraccarico raccoglie la funzione che più si avvicina all'argomento fornito. È fornito un test. Nessuna conversione necessaria - la conversione di identità utilizzata. Così sceglie risoluzione funzione F (Test). Test non può essere copiato da rvalue, che avete fornito, ma la risoluzione di sovraccarico è riuscito già ... conversione in int non è mai verificata.

g(Eater) viene scelto perché i tipi non corrispondono esattamente, la conversione di identità non viene utilizzato, e il compilatore deve trovare una routine di conversione che le opere. g(Slurper) non perché non si può fare uno su l'argomento in dotazione.

"Perché non questo venga meno struct A { operator int(); }; void f(A&); void f(int); void g() { f(A()); }"

A causa f (A &) non è un sovraccarico valida per l'argomento in dotazione. In questo caso il parametro è un punto di riferimento e il fatto che temps non si legano al non-const è permesso di effettuare la risoluzione. In questo caso si fa e la cui versione della funzione diventa un non-candidato, lasciando solo quello e funziona.

Altri suggerimenti

In sostanza, per la risoluzione di sovraccarico, si presume che un oggetto di tipo A può essere convertito in un oggetto di tipo A prescindere da qualsiasi cv-qualificazione per uno dei due.

Da progetto n1905:

13.3.3.1: Overloading.Overload Resolution.Best valida Function.Implicit Sequenze di conversione

6 Quando il tipo di parametro non è un riferimento , impliciti modelli di sequenza conversione copia-inizializzazione del parametro dall'espressione argomento. La sequenza conversione implicita è quella richiesta per convertire l'argomento espressione di un rvalue del tipo di parametro. [ Nota : quando il parametro ha un tipo di classe, questo è un concettuale conversione definiti ai fini della clausola 13; l'inizializzazione attuale viene definito in termini di costruttori e non è una conversione. - Nota finale ] Qualsiasi differenza di livello superiore cv-qualificazione si confonde con l'inizializzazione stesso e lo fa non costituisce una conversione [ Esempio :. un parametro di tipo A può essere inizializzato da un argomento di tipo const A. La sequenza di conversione implicita per questo caso è la sequenza di identità; non contiene la “conversione” da A a const A. - esempio end ] Se il parametro ha un tipo di classe e l'espressione argomento ha lo stesso tipo, l'implicito sequenza di conversione è una conversione di identità . [...]

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top