1

I have some container-using code that is causing me grief. The issue is that I want to put a smart pointer (unique_ptr) in one of the subfields. Eg:

struct subrecord {
    int id;
    int handle;
    std::list<std::unique_ptr<some_really_big_record>> update; // <-- Problem field
};

struct database {
    std::map <std::string, subrecord> name_subrec_map;
    std::vector <std::string> a_names;
    std::vector <std::string> b_names;
};

Everything compiled just fine until I tried adding that update field. Once I did that, the compiler started to complain that there's no usable copy operator for that unique_ptr. That's fair enough, it isn't supposed to have one. I wasn't intending these map entries to be copied anyway.

However, the compiler is not telling me where in my code this copy is coming from. There's rather a lot of it by now. Is there any good way to tell? I've tried searching for references to update and name_subrec_map and commenting them out, but haven't had any luck at all. The only thing that gets rid of the error is commenting out that update field itself.

I'd hate to have to switch to a shared_ptr, just because I can't find the dang copy.

T.E.D.
  • 44,016
  • 10
  • 73
  • 134
  • Your compiler gave you an error message but no line/file to go with it? – Borgleader Jan 14 '15 at 16:39
  • Try compiling with vaguely recent versions of g++ or clang. They will tell you exactly where the copy is being instantiated. Actually, any version that supports `unique_ptr` should tell you that. – juanchopanza Jan 14 '15 at 16:39
  • @juanchopanza If it supports unique_ptr isn't it by default a vaguely recent version of g++/clang? – Borgleader Jan 14 '15 at 16:40
  • @Borgleader - The line numbers it is giving me for this error are all off in the compiler's own template code. VS2012 error messages FTL! – T.E.D. Jan 14 '15 at 16:44
  • 2
    @T.E.D.: the line numbers are not all in the compiler's code. look for the file names. – Cheers and hth. - Alf Jan 14 '15 at 16:46
  • 2
    [Related issue?](http://stackoverflow.com/questions/26160396/map-of-lists-of-move-only-type-wont-compile) – Borgleader Jan 14 '15 at 16:46
  • 2
    unique_ptr is not copyable (although it is movable). As a result subrecord is also non-copyable (but is movable). if you are copying subrecord anywhere it is going to give you the same error. As a test put subrecord( const subrecord & ) = delete; subrecord( subrecord&& ) = default; Might make it easier to find the error in your code then – CashCow Jan 14 '15 at 16:48
  • @Cheersandhth.-Alf - Oh yes they are. Every single error message is either calling out a line in `...\VC\include\list` or in `...\VC\include\xmemory0`, except for the last that just points to the first template instantiation off in a header file of mine. – T.E.D. Jan 14 '15 at 16:50
  • @Borgleader, GCC 4.4 supported `unique_ptr` but is not very recent (although it would still tell you where the copy was required from) – Jonathan Wakely Jan 14 '15 at 16:51
  • he can't run it through a debugger to find compiler errors.. – CashCow Jan 14 '15 at 16:53
  • 1
    @T.E.D. are you _sure_ the compiler isn't also showing you the call stack that led to the error inside the library? GCC and Clang will print something like "required from ...; required from ...;" to show how an error in a header was reached, so you can trace it back to your own code. I would be amazed if VC++ doesn't do that too. The relevant lines might not start with the word "error" – Jonathan Wakely Jan 14 '15 at 16:53
  • @JonathanWakely - Be amazed, because it doesn't. At least not the VS2012 build I'm using. Perhaps more recent versions of the compiler are better. – T.E.D. Jan 14 '15 at 17:28
  • @Borgleader - After futzing around with things as suggested, I think you are most likely correct that this is the same bug as [this issue](http://stackoverflow.com/questions/26160396/map-of-lists-of-move-only-type-wont-compile). Damn shame the compiler had to make things so difficult to track down. – T.E.D. Jan 14 '15 at 17:42

1 Answers1

3

If your code somewhere is copying subrecord it may be getting hidden in your error messages.

As subrecord is movable but not copyable, you can put this in its header:

 struct subrecord 
 { 
       // ...

       subrecord( const subrecord & ) = delete;
       subrecord( subrecord&& ) = default;
 };

You might even temporarily comment out the list member and see if any compiler errors come up where this copy is being invoked.

NOTE:

If your compiler doesn't support delete and default, make the copy constructor private but also you have to make the move constructor public.

If this is just a temporary measure to find a compiler error, you can skip implementing it as you don't care about link errors. You'll remove it later, but will have to also remove the private copy-constructor.

Although it is preferential that you do implement it because that will expose any further attempts in the code to copy a subrecord without giving whoever dares to do it compiler error message hell.

CashCow
  • 30,981
  • 5
  • 61
  • 92
  • OK. Deleted previous comment, as the error I got was (as you suspected) due to not making the move constructor visible. Oddly, when I do this, everything compiles. Like there is in fact no copy. The most logical explanation here is probably that @borgleader is right, and I've stumbled over the compiler bug mentioned in [this question](http://stackoverflow.com/questions/26160396/map-of-lists-of-move-only-type-wont-compile) – T.E.D. Jan 14 '15 at 17:41
  • Ok that doesn't surprise me with VC12 that it isn't fully compliant – CashCow Jan 14 '15 at 17:50
  • Honestly, I'm just happy to not be using VS6 anymore. :-) – T.E.D. Jan 14 '15 at 19:01