Question

To learn about the intricacies of C++11 I am playing aroung with unique_ptr a bit.

I wonder, is there any way to use iota to initialize an Container of unique_ptr?

I started with the unique-ptr-less solution which works fine:

std::vector<int> nums(98); // 98 x 0
std::iota(begin(nums), end(alleZahlen), 3); // 3..100

Now lets do it as far as we can using unique_ptr

std::vector<std::unique_ptr<int>> nums(98); // 98 x nullptr
std::unique_ptr three{ new int{3} };
std::iota(begin(nums), end(nums), std::move{three});

This fails obviously. Reasons:

  • Although I marked three with move as a && this may not be sufficient to copy/move the initial value into the container.
  • ++initValue will also not work, because initValue is of type unique_ptr<int>, and there is no operator++ defined. But: we could define a free function unique_ptr<int> operator++(const unique_ptr<int>&); and that would take care of that at least.
  • But to copy/move the results from that operation is again not permitted in unique_ptr and this time I can not see how I could trick the compiler into using move.

Well, that's where I stopped. And I wonder if I miss some interesting idea on how to tell the compiler that he may move the results of the operator++. Or are there other hindrances, too?

Was it helpful?

Solution

In order to end up with 98 instances of unique_ptr, there must be 98 calls to new. You attempt to get away with just one - that can't possibly fly.

If you are really intent on pounding a square peg into a round hole, you could do something like this:

#include <algorithm>
#include <iostream>
#include <memory>
#include <vector>

class MakeIntPtr {
public:
  explicit MakeIntPtr(int v) : value_(v) {}
  operator std::unique_ptr<int>() {
    return std::unique_ptr<int>(new int(value_));
  }
  MakeIntPtr& operator++() { ++value_; return *this; }
private:
  int value_;
};

int main() {
  std::vector<std::unique_ptr<int>> nums(98);
  std::iota(begin(nums), end(nums), MakeIntPtr(3));

  std::cout << *nums[0] << ' ' << *nums[1] << ' ' << *nums[2];
  return 0;
}

OTHER TIPS

Maybe std::generate_n is a better algorithm for this?

std::vector<std::unique_ptr<int>> v;
{
    v.reserve(98);
    int n = 2;
    std::generate_n(std::back_inserter(v), 98,
                    [&n]() { return std::make_unique<int>(++n); });
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top