Search code examples
c++c++11unique-ptriota

Initialize a Container of unique_ptr with iota


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?


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;
    }