1

I have a function that forwards some large variables via const reference like this:

void processMore(const std::vector<int> &a, const std::vector<int> &b);

void process(const std::vector<int> &a,
             const std::vector<int> &b) {
  processMore(a, b);
}

But I have added an optimisation that modifies them:

std::pair<std::vector<int>, std::vector<int>>
optimise(const std::vector<int> &a, const std::vector<int> &b);

I can do it unconditionally like this:

void process(const std::vector<int> &a,
             const std::vector<int> &b) {
  auto opt = optimise(a, b);
  processMore(opt.first, opt.second);
}

But I want to make it optional. My solution is this:

void process(const std::vector<int> &a,
             const std::vector<int> &b,
             bool doOptimisation) {
  auto opt =
      [&]() -> std::pair<const std::vector<int>&,
                         const std::vector<int>&> {
    if (doOptimisation) {
      auto o = optimise(a, b);
      return std::make_pair(o.first, o.second);
    }
    return std::make_pair(a, b);
  }();
  processMore(opt.first, opt.second);
}

This seems a bit convoluted. Is there a better way? I want to avoid unnecessary copying.

5
  • 4
    Red alert! Your lambda returns a pair of dangling references that refer to the dead o! Commented Apr 16, 2019 at 9:45
  • with "unnecessary" do you mean in case you dont do the optimization or also in case you do it? Commented Apr 16, 2019 at 9:45
  • With your current lambda, why not just simply return optimise(a, b);? Commented Apr 16, 2019 at 9:45
  • @Quentin: Ah yeah I did think about that but was thinking that const references would extend the lifetime. I guess that doesn't extend outside the lambda. Commented Apr 16, 2019 at 9:48
  • @Someprogrammerdude: Because optimise() returns a pair of values, and I need a pair of references. Commented Apr 16, 2019 at 9:49

2 Answers 2

3

The "naive" solution would be something like

if (doOptimisation)
{
    auto o = optimise(a, b);
    processMore(o.first, o.second);
}
else
{
    processMore(a, b);
}

No extra copying being made.

Sign up to request clarification or add additional context in comments.

4 Comments

Ah yeah I guess I should say that processMore() is actually quite a lot of code, so I don't really want to write it all twice.
@Timmm it is a function that you simply call twice. If it isnt in you real code then the solution is to use a function ;)
Ah I see what you mean. I mean, when I said processMore() is a lot of code I didn't mean the code in processMore() is a lot of code - I meant that the code in process() is a lot longer than just calling one function. But I guess I can put all that code in another function.
@Timmmm: Exactly, but that's effectively what your lambda is. This question is sort of moot because it was framed in a way that doesn't match your real code.
0

Another option is this:

void process(const std::vector<int> &a,
             const std::vector<int> &b,
             bool doOptimisation) {
  std::optional<std::pair<std::vector<int>, std::vector<int>>> opt;
  if (doOptimisation) {
    opt = optimise(a, b);
  }
  const auto &aOpt = opt ? opt->first : a;
  const auto &bOpt = opt ? opt->second : b;

  processMore(aOpt, bOpt);
}

This is simpler than repeating processMore() or moving it into another wrapper function in my actual code (it's hard to convey complicated code in a minimal example).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.