9

I have a function:

void AddImage(const Image &im);

This function does not need image to be modifiable, but it stores the image a const reference to be used later. Thus, this function should not allow temporaries. Without any precaution the following works:

Image GetImage();

...

AddImage(GetImage());

Is there a way to prevent this function call?

Cem Kalyoncu
  • 14,120
  • 4
  • 40
  • 62
  • 1
    In addition to the immediate problem also consider lifetime issues. In your current design the caller is responsible to ensure that the image lives as long as long as it may be used by the callee. Asymmetric ownership like this could lead to serious problems. Without more context I can’t say if that’s the case in your code. It’s definitely something to watch out for carefully. – besc Nov 24 '16 at 17:31
  • That is absolutely true. However, this is quite an oversimplification of the working system. In the working system AddImage is a member function of animation object and the lifetimes of images and the animation object is synced (they are the members of the same class, generally). To make sure not to have any trouble with destruction sequence, animation does not inspect its children during destruction. – Cem Kalyoncu Nov 24 '16 at 17:38

1 Answers1

14

There are couple of mechanisms that prevent passing temporary to a const ref parameter.

  1. Delete the overload with r-value parameter: void AddImage(const Image &&) = delete;

  2. Use const pointer: void AddImage(const Image*) . This method will work pre-C++11

  3. Use reference wrapper: void AddImage(std::reference_wrapper<const Image>)

First method should be preferred when using C++11 supporting compiler. It makes the intention clear. Second method requires a runtime check of nullptr and does not convey the idea that the image cannot be null. Third method works and makes the intention clear, however, it is too explicit.

Cem Kalyoncu
  • 14,120
  • 4
  • 40
  • 62
  • 1
    Now I can detect problems with passing temporaries at compile-time. Thanks a lot! – eudoxos Mar 23 '19 at 19:34
  • I would really appreciate if you could elaborate more on how `std::reference_wrapper` works in this case. What happens if the arguments is a temporary obj `std::string`, and the function returns a pointer to its `.data()`? Will it work in this case? – Kostiantyn Ponomarenko Apr 21 '20 at 08:30
  • I think (not sure) 3rd option uses a constructor with r-value overload deleted. Thus it will prevent temporary to be passed as a reference. – Cem Kalyoncu Apr 22 '20 at 09:17
  • Note that option 1 requires linearly (or exponential, if you want to avoid ambiguity) many overloads if you have multiple const reference arguments which you need prevent temporaries from being passed. – Edward Z. Yang Jun 17 '20 at 18:26
  • 1
    What is meant by the third method being "too explicit"? – Mark H Feb 25 '21 at 19:05
  • Means you are writing way too much for the task. – Cem Kalyoncu Feb 27 '21 at 03:12