Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
317 views
in Technique[技术] by (71.8m points)

c++ - Function that accepts both lvalue and rvalue arguments

Is there a way to write a function in C++ that accepts both lvalue and rvalue arguments, without making it a template?

For example, suppose I write a function print_stream that reads from an istream and prints the data that was read to the screen, or something.

I think it's reasonable to call print_stream like this:

fstream file{"filename"};
print_stream(file);

as well as like this:

print_stream(fstream{"filename"});

But how do I declare print_stream so that both uses work?

If I declare it as

void print_stream(istream& is);

then the second use won't compile because an rvalue will not bind to a non-const lvalue reference.

If I declare it as

void print_stream(istream&& is);

then the first use won't compile because an lvalue will not bind to an rvalue reference.

If I declare it as

void print_stream(const istream& is);

then the function's implementation won't compile because you can't read from a const istream.

I can't make the function a template and use a "universal reference", because its implementation needs to be separately compiled.

I could provide two overloads:

void print_stream(istream& is);
void print_stream(istream&& is);

and have the second call the first, but that seems like a lot of unnecessary boilerplate, and I would find it very unfortunate to have to do that every time I write a function with semantics like this.

Is there something better I can do?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There is not much of a sane choice other than offering two overloads or making your function a template, I would say.

If you really, really need an (ugly) alternative, then I guess the only (insane) thing you can do is to have your function accept a const&, with a pre-condition saying that you cannot pass an object of a const-qualified type to it (you don't want to support that anyway). The function would then be allowed to cast away the constness of the reference.

But I'd personally write two overloads and define one in terms of the other, so you do duplicate the declaration, but not the definition:

void foo(X& x) 
{ 
    // Here goes the stuff... 
}

void foo(X&& x) { foo(x); }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...