https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80284

            Bug ID: 80284
           Summary: Support of associative containers with incomplete
                    element type
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: frankhb1989 at gmail dot com
  Target Milestone: ---

https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.201z
shows that "the feature" of N4510 (except the feature-test macro) has been
supported long ago from 3.0. It is not very clear whether "the feature" is
applicable on other containers not currently required by the proposed (and
accepted by the working draft) rules of N4510 yet.

I don't find the answer in the documentation, but I still tend to guess other
containers can work in libstdc++, for several reasons:

1. N4510 mentions associative/unordered containers as well. It just not ready
to require it for all implementations.
2. N4510 mentions boost.containers in parallel, which clearly states the
support of incomplete element types for other containers in its documentation.
3. They (from libstdc++) can actually work as expected (at least for naive
cases).

The real problem raises when I meet some not-so-naive cases. Test case:

#include <map>
#include <string>

using namespace std;

struct node
{
        using container_t = map<string, node>;
        string name;
        container_t container;

        node(const string& n)
                : container(), name(n)
        {}
        node(container_t&& con, const string& s)
                : container(move(con)), name(s)
        {}

        void
        swap(node& nd) noexcept
        {
                name.swap(nd.name);
                container.swap(nd.container);
        }
};

int main()
{
        node n(node::container_t{{"a", node("a")}}, "A");
        n.swap(n.container.begin()->second);
}

Despite the undefined behavior caused by incomplete template argument as per
the standard, it seems well-formed. However, it leaks. I've reproduced it on
GCC 5.3 + DrMemory on Windows/GCC 6.3.1 + valgrind on Linux. It can also
reproduced with clang++ instead of g++.

Is it intended by design?

Reply via email to