Tworzenie nienazwanego obiektu w wywołaniu funkcji

0

Nie rozumiem pewnego zachowania a mianowicie mam jakąś klasę a w niej metodę

void out( std::ostream & out = std::cout );

I teraz pytanie dlaczego mogę ten kod wywołać tak

base.out( std::cout );

a nie mogę wywołać tak

base.out( std::ofstream( "log.txt" ) );

bo dostaje ( co jest dla mnie oczywiste ) błąd

no matching function for call to 'base::out(std::ofstream)'

pytanie dlaczego w wersji z obiektem std::cout się nie czepia?
Wiem że mogę to zrobić tak

std::ofstream file( "log.txt" );
base.out( file );

Pytam bo jest to dla mnie dziwne i chciałbym aby mi to ktoś wyjaśnił.

1

Dla takiej: void out( const std::ostream & out = std::cout ); wszystko przejdzie gładko.
Ponieważ tu: std::ofstream("log.txt") ma typ const std::ofstream a tego nie da się skonwertować do std::ofstream & o czym ci wyraźnie mówi kompilator.

3

Obiekty tymczasowe mogą być przypisane tylko do stałych referencji albo do referencji do r-value. Więc albo dopisz const do argumentu tej funkcji out albo poczytaj o r-value references.

0

Pokaż konkretny kod (nie) dający się skompilować i uruchomić, bo to co podajesz u mnie działa.

0

@_13th_Dragon jak dam

void out( const std::ostream & out = std::cout );

to nic do tego strumienia nie zapisze a przecież o to mi właśnie chodzi, strumień nie może być const...

0

@Azarien przykład prezentujący problem nie dający się skompilować

class base
{
public:

    void out( std::ostream & out = std::cout ) {
        out<< "c++" <<std::endl;
    }
};


int main()
{

    base temp;
    temp.out();   // ok
    temp.out( std::cout );   // ok
    temp.out( std::ofstream( "log.txt" ) );     // no matching function for call to
                                                //    base::out( std::ofstream )

}

2

Tak jak @Endrju wspomniał możesz użyć referencji do r-wartości, np:

 
void print(std::ostream&& out = std::move(std::cout))
{
	out << "qwerty\n";
}

int main() 
{
	print(); 
	print(std::ofstream("qwerty"));
	return 0;
}

Albo dodać const i castować const std::ostream& na std::ostream&, np:

 
void print(const std::ostream& out = std::cout)
{
        std::ostream& non_const_out = const_cast<std::ostream&>(out);
	non_const_out << "qwerty\n";
}

int main() 
{
	print(); 
	print(std::ofstream("qwerty"));
	return 0;
}
</del>
1
class base
{
public:
 
    void out( std::ostream & out = std::cout ) {
        out<< "c++" <<std::endl;
    }
};
 
 
int main()
{
 
    base temp;
    temp.out();   // ok
    temp.out( std::cout );   // ok
    std::ofstream fout( "log.txt" )
    temp.out( fout );    // ok
    return 0;
}
4

@Satirev drugi kod to jest przecież undefined behavior. Tymczasowy obiekt jest const i nie można go modyfikować, const_cast tego nie zmienia.

Poza tym to straszne potwory. Po prostu trzeba ten strumień ustanowić normalną zmienną na stosie (jak wyżej napisał @_13th_Dragon) i będzie bez problemów, po co takie dziwaczne kombinacje?

1 użytkowników online, w tym zalogowanych: 0, gości: 1