2

How to write a function return std::seed_seq object?

The code below don't work.

std::seed_seq f(){
    return {0};
}

std::seed_seq s = f();  /* error C2280: 
                           'std::seed_seq::seed_seq(const std::seed_seq &)':
                           attempting to reference a deleted function
                         */
J. Doe
  • 632
  • 1
  • 4
  • 11
  • 1
    Which compiler is this? Seems to [compile fine here](http://cpp.sh/7nfwl). That definitely should not invoke a copy construction because of [RVO](https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization) – Cory Kramer Apr 13 '17 at 13:02
  • @CoryKramer VC++2017 – J. Doe Apr 13 '17 at 13:04
  • 7
    @CoryKramer your compiler may be using guaranteed copy-elision, not available in C++11 – Piotr Skotnicki Apr 13 '17 at 13:04
  • Could you force the behavior with `std::seed_seq s = std::move(f());`? – Cory Kramer Apr 13 '17 at 13:07
  • @CoryKramer This won't work either - A move is not an ellision, and the move-constructor of `std::seed_seq` is implicitly deleted by the explicit deletion of the copy constructor. – Holt Apr 13 '17 at 13:08
  • @CoryKramer [Can repro here](http://coliru.stacked-crooked.com/a/5e4414c11e9f7887) – Borgleader Apr 13 '17 at 13:10
  • @CoryKramer Tried, no luck. – J. Doe Apr 13 '17 at 13:13
  • 1
    What do you aim to do @J.Doe – coincoin Apr 13 '17 at 13:13
  • Why not return a `std::initializer_list` and have the object constructed at the call site from that? – NathanOliver Apr 13 '17 at 13:18
  • @coincoin It's like a seeds lookup table. But huge. For a given lookup key, the seeds should not change. I can just return a vector. But I think a seed_seq would be much better. – J. Doe Apr 13 '17 at 13:19
  • 1
    @J.Doe What do you use the seed for after retrieving them from your lookup table? Maybe you could return const reference if it suits your needs. – Holt Apr 13 '17 at 13:22
  • 1
    I copied the code of std::seed_seq and removed the delete declaration. Hope I didn't violate anything. – J. Doe Apr 13 '17 at 13:38

1 Answers1

2

You can't.

Apparently the Standard does not see a reason to make it copyable, as it is just a temporary object to generate proper seed sequence out of small input. Why it is not moveable is a bit questionable, but probably the answer is within the same frame of reasoning as for the copy.

There are few workarounds though:

  1. Use the heap i.e. return a pointer to the seed sequence:

    auto seq = std::make_unique<std::seed_seq> (/*...*/);
    // ...
    return seq;
    
  2. After generation, instead of returning the std::seed_seq object itself, just copy its content into another store.

    std::seed_seq seq (/*...*/);
    // ...
    std::vector<std::seed_seq::result_type> seeds (seq.size ());
    seq.param (seeds.begin ());
    
  3. The other way around. Store the input to std::seed_seq instead. That's what I did at the end. There is no real difference between whether you will keep what was stored or what you are going to store there - the Standard guarantees that. It is just that you can decide to do something with the seeds before passing them to std::seed_seq e.g. setting them to concrete values for debug purposes.

Rado
  • 766
  • 7
  • 14