11

I'm working on Linux gcc environment and I need to initilize function arguments that are classes with default values. When I do that with temporary instance of the class it makes an error like this: "default argument for [function argument] has type [class name]. for example:

void foo(std::wstring& str = std::wstring())

error: default argument for 'std::wstring& str' has type 'std::wstring' P.S. this code is compiled without any error or warning with VC++.

How can I initilize the default value?

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
mle977
  • 123
  • 1
  • 4
  • what are you trying to achieve? To me, it looks meaningless what you are doing.. – Simone Nov 21 '10 at 13:49
  • 1
    @Simone -this is probably a trial to get both adventages of default values and sending by reference. – rkellerm Nov 21 '10 at 13:52
  • binding to non-const references is not standard compliant, but VC++ allows it as an extension AFAIK. – Matthieu M. Nov 21 '10 at 17:23
  • Found this article on lvalues and rvalues and const helpful: https://www.internalpointers.com/post/understanding-meaning-lvalues-and-rvalues-c – Aaron Swan Jan 17 '23 at 19:22

3 Answers3

11

This is supposed to not compile. You are trying to bind an rvalue to a non-const reference. Say std::wstring const & str and it should work.

dennycrane
  • 2,301
  • 18
  • 15
10

You could just create a function overload:

void foo() {
    std::wstring str;
    foo(str);
}

but I really miss the point.

EDIT: I mean, that function's purpose is almost certainly to modify an input string. If you provide an empty input string that you can't access later, why bother?

Simone
  • 11,655
  • 1
  • 30
  • 43
  • Function's purpose can be also get the input string without modifying it at all. The passing by reference can be also for preventing the copy constructor from being called. – rkellerm Nov 21 '10 at 14:27
  • there are many situations where it could be useful, say for example that this isn't a string, but a buffer, or that some data (like detailed logs) is put there by the method but you only care about the result. Your solution gently solves the issue with standard compliant code nonetheless :) – Matthieu M. Nov 21 '10 at 17:27
  • @rursw1 yes, but - in such cases - if you don't pass a **const** reference I think the function's interface is somehow wrong. – Simone Nov 22 '10 at 07:09
6

You cannot bind non-const references to rvalues. Passing by value would work:

void foo(std::wstring str = std::wstring())

Or passing by reference-to-const:

void foo(const std::wstring& str = std::wstring())
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • I don't really understand your last sentence. Even if the compiler doesn't optimize out the temporary and the copy how expensive is copying an empty string really going to be? And if the temporary is elided, what's left to move? – CB Bailey Nov 21 '10 at 17:33
  • @Charles: What if a user *does* supply a string as an argument? Then it must be copied in C++03. – fredoverflow Nov 21 '10 at 17:35
  • Sorry, I thought you were referring to the use of the default argument in your comment. In any case, if the user supplies a string that is a temporary in many cases it can be elided in C++03. A copy doesn't always have to happen. – CB Bailey Nov 21 '10 at 17:38
  • @Charles: Right, let me rephrase that: what if the argument is an lvalue of type wstring? :) – fredoverflow Nov 21 '10 at 17:41
  • Then it as to be copied in either C++03 or C++0x. You can only move from rvalues (xvalues or prvalues). [I'm not quite sure where this inquisition is heading?] – CB Bailey Nov 21 '10 at 17:46
  • @Charles: Right... I guess I should probably just remove the last sentence :) – fredoverflow Nov 21 '10 at 17:50