On a forwarding bug

Recently I got caught into a funny bug with forwarding references that I want to share here. In theory, I knew all the principles that led to it, but then it turned out that it was not easy for me to see how they apply precisely and to understand their full extent. Maybe reading this can save a few hours of your time someday.

Let’s start with a code snippet.

  struct element
    {
    int v=0;
    };

    template<class What>
  struct holder
    {
    What what;
    holder(What&& w) : what(w) {}
    };

    template<class T>
  auto make_holder(T&& t) -> auto
    {
    return holder<T>(std::forward<T>(t));
    }

  auto ret_holder1(void) -> auto
    {
    element vl{17};
    auto h = make_holder(std::move(vl));
    // use h
    return h;
    }

  auto ret_holder2(void) -> auto
    {
    element vl{17};
    auto h = make_holder(vl);
    return h;
    }

  auto main(void) -> int
    {
    auto rh1 = ret_holder1();
    auto rh2 = ret_holder2();
    return 0;
    }

This builds and runs, but some of it is broken. Do you feel uneasy why this compiles in the first place? Can you see the bug(s) already?
Read more of this post

Advertisements