4

Could someone please tell me why this does not work? I was under the impression that C++ would automatically pass the reference of the return-by-value function result to the constructor, but it complains that no matching operator could be found.

class bucket_string {
        public:
            bucket_string();
            bucket_string(bucket_string & rhs);
            bucket_string & operator=(bucket_string & rhs);
            virtual ~bucket_string();

            bucket_string substr(iterator start, iterator end){
                        bucket_string b(str);
                        return b;
                    }
 };



bucket_string bs("the quick brown fox jumps over the lazy dog");
bucket_string bs1 = bs.substr(bs.begin(), bs.end());

returns the following error:

error: no matching function for call to ‘bucket_string::bucket_string(bucket_string)’
note: candidates are: bucket_string::bucket_string(bucket_string&)
      bucket_string::bucket_string()
Alon
  • 1,776
  • 13
  • 31
Supy
  • 180
  • 2
  • 10
  • 4
    I'm surprised that you don't get an error about no match for `bucket_string::bucket_string(const char*)`. Is this your complete code? Also, where is `iterator` declared? – CB Bailey Mar 26 '13 at 07:40
  • No it is not - I removed most of it to make it easier to read and answer my question :-) – Supy Mar 26 '13 at 07:44
  • Your example code should be complete as well as minimal and the errors that you show should come from the code that you actually have in your question not some different code that you haven't shown. Doing this gives question answers a fighting chance of helping you with the actual problem that you are having. – CB Bailey Mar 26 '13 at 07:49
  • Fair enough Charles. I knew that my problem was coming from an incompatibility of return and argument types though, I just wasn't sure what it was. The complete code is much, much longer and largely irrelevant to the problem I was having though. I see your point though. – Supy Mar 26 '13 at 07:52
  • I'm sorry, I didn't make myself clear. Your posted code doesn't have to be _the_ complete code, it just has to be complete in the sense of internally consistent and consistent with the errors that you show. An answerer should be able paste the code into the input of their compiler and see the error that you post. – CB Bailey Mar 26 '13 at 07:56

3 Answers3

7

In C++, temporary values cannot be bound to non-const references.

Your bucket_string substr(iterator start, iterator end) function returns a temporary, and your constructor/assignation operator take a non-const reference as a parameter hence your problem.

Thus you need to add the missing const specifier to your constructor and assignation operator. Like so:

bucket_string(const bucket_string& rhs);
bucket_string& operator=(const bucket_string& rhs);

Here is an interesting discussion on the topic for a better understanding.

On a side note, and if C++11 is an option, you may also make your class movable. This would allow the internal resources of your temporary to be transferred to another instance. We lack context to say if that would be a good thing in your situation.

You would then have to implement those methods:

bucket_string(bucket_string&& other);
bucket_string& operator=(bucket_string&& other);
Community
  • 1
  • 1
ereOn
  • 53,676
  • 39
  • 161
  • 238
  • Accepted this answer (even though M M's answer did the trick for me) as it is a little more explanatory for anyone who might stumble across this question. – Supy Mar 26 '13 at 07:54
6

Put some const.

bucket_string(const bucket_string & rhs);
              ^^^^^
bucket_string & operator=(const bucket_string & rhs);
                          ^^^^^

You're passing a temporary const values to the constructor. Compiler is searching for a constructor which accpets const reference:

bucket_string bs("the quick brown fox jumps over the lazy dog");
masoud
  • 55,379
  • 16
  • 141
  • 208
1

The code mixes value and reference semantics in a way that doesn't work. substr returns by value but the constructor takes a parameter by non-const reference. Being non-constant indicates that the parameter will be treated as a modifiable object, not a pure value. The language forbids using references in this way. Adjust the assignment operator so it can't modify its argument:

        bucket_string & operator=(bucket_string const & rhs);

This works because C++ will allow a temporary object (such as a function return value) to be passed through a const reference.

If you actually do want to modify the source of the assignment operation, then C++ offers a solution in rvalue references. Instead of const & use &&. But the assignment would no longer be idempotent, so it would be called move assignment and you would need alternate syntax when using non-temporary objects.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421