web-dev-qa-db-fra.com

C ++ - l'instruction ne peut pas résoudre l'adresse de la fonction surchargée

Lorsque je tape ce qui suit en tant que ligne autonome:

std::endl;

J'ai eu l'erreur suivante:

statement cannot resolve address for overloaded function

Pourquoi donc? Je ne peux pas écrire std::endl; en tant que ligne autonome?

Merci.

20
Simplicity

std::endl est un modèle de fonction. Normalement, il est utilisé comme argument de l'opérateur d'insertion <<. Dans ce cas, le operator<< Du flux en question sera défini comme par ex. ostream& operator<< ( ostream& (*f)( ostream& ) ). Le type de l'argument de f est défini, donc le compilateur saura alors la surcharge exacte de la fonction.

C'est comparable à ceci:

void f( int ){}
void f( double ) {}
void g( int ) {}
template<typename T> void ft(T){}

int main(){
  f; // ambiguous
  g; // unambiguous
  ft; // function template of unknown type...
}

Mais vous pouvez résoudre l'ambiguïté par quelques indices de type:

void takes_f_int( void (*f)(int) ){}

takes_f_int( f ); // will resolve to f(int) because of `takes_f_int` signature
(void (*)(int)) f; // selects the right f explicitly 
(void (*)(int)) ft; // selects the right ft explicitly 

C'est ce qui se passe normalement avec std::endl Lorsqu'il est fourni en argument à operator <<: Il existe une définition de la fonction

 typedef (ostream& (*f)( ostream& ) ostream_function;
 ostream& operator<<( ostream&, ostream_function )

Et cela permettra au compilateur de choisir la bonne surcharge de std::endl Lorsqu'il est fourni par ex. std::cout << std::endl;.

Bonne question!

16
xtofl

std::endl est un modèle de fonction. Si vous l'utilisez dans un contexte où l'argument modèle ne peut pas être déterminé de manière unique, vous devez lever l'ambiguïté de la spécialisation que vous voulez dire. Par exemple, vous pouvez utiliser une distribution explicite ou l'affecter à une variable du type correct.

par exemple.

#include <ostream>

int main()
{
    // This statement has no effect:
    static_cast<std::ostream&(*)(std::ostream&)>( std::endl );

    std::ostream&(*fp)(std::ostream&) = std::endl;
}

Habituellement, vous l'utilisez simplement dans un contexte où l'argument modèle est déduit automatiquement.

#include <iostream>
#include <ostream>
int main()
{
    std::cout << std::endl;
    std::endl( std::cout );
}
3
CB Bailey

La raison la plus probable à laquelle je peux penser est que sa déclaration est:

ostream& endl ( ostream& os );

En d'autres termes, sans faire partie d'un << opération, il n'y a pas de os qui puisse être déduit. Je suis assez certain que c'est le cas depuis la ligne:

std::endl (std::cout);

compile très bien.

Ma question est la suivante: pourquoi voudriez-vous vouloir faire cela?

Je sais pertinemment que 7; est une déclaration parfaitement valide en C mais vous ne voyez pas ce genre de détritus polluer mon code :-)

3
paxdiablo

endl est une fonction qui prend un paramètre. Voir std :: endl sur cplusplus.com

// This works.
std::endl(std::cout);
2
sinelaw

http://www.cplusplus.com/reference/iostream/manipulators/endl/

Vous ne pouvez pas avoir std::endl Seul car il nécessite un basic_ostream Comme type de paramètre. C'est la façon dont il est défini.

C'est comme essayer d'appeler my_func() lorsque la fonction est définie comme void my_func(int n)

2
Marlon

std :: endl est un manipulateur. C'est en fait une fonction qui est appelée par la version a de l'opérateur << sur un flux.

std::cout << std::endl
// would call 
std::endl(std::cout).
2
hbn

Le std::endl termine une ligne et vide le tampon. Il devrait donc être connecté au flux comme cout ou similaire.

1
Alexander Chuikov