The std :: vector declaration works with advanced declared classes ..?

I have a header file as below -

// abc.hpp #include <vector> #include <string> namespace A { namespace B { struct abc { std::string _type; }; using abc_vector = std::vector<abc>; } } 

I am using a direct declaration in another header file.

 // con.hpp #include <vector> namespace A { namespace B { struct abc; // Forward Declaration using abc_vector = std::vector<abc>; } namespace C { class N { public: B::abc_vector foo(std::string type); }; } } 

What really bothers me is that my code compiles and works.

How to declare a vector with an incomplete type ..? I think he will not be able to solve the size of abc .

 using abc_vector = std::vector<abc>; 

Below is the code that I used to check my header files. It is strange that it compiles and works fine.

 #include "con.hpp" #include "abc.hpp" #include <iostream> namespace A { namespace C { B::abc_vector N::foo(std::string type) { B::abc a; a._type = type; B::abc_vector d; d.push_back(a); return d; } } } int main() { A::C::N n; auto container = n.foo("test"); for (const auto& i : container) std::cout << i._type << ' '; return 0; } 
+4
source share
3 answers

This is an interesting topic (at least for me) and applies to other std containers.

Initially, the standard made undefined behavior to create an incomplete type container. However, the implementation did not ban it. This was, in all likelihood, not a deliberate, but simply a side effect of the fact that the elements in (for example, a vector) are stored in the memory cell referenced by the pointer.

Thus, the size of the element does not have to be known until the element is actually needed - during the creation of the member function of the vector.

Here is a starting point for research if you want to explore further:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4056.html

+2
source

Code line

 using abc_vector = std::vector<abc>; 

only introduces a type alias for std::vector<abc> . This does not require at least the size of abc , since an object of type abc is not allocated at all. Only the new type is declared.

 B::abc_vector d; 

Really need a definition of abc . However, this works because at this point abc already defined, because the abc.hpp header file was included.


You mean this answer where

 std::vector<B> v; 

"done." This is not the same as you. You just entered a type alias. std::vector<B> v; Actually defines a variable. Therefore, the definition of B is mandatory.


note that

 using abc_vector = std::vector<abc>; 

equivalently

 typedef std::vector<abc> abc_vector; 

Maybe this will simplify a little why the size of abc not required to be known at a given time in compilation.

+3
source

There is an interesting observation. Both GCC5.2 and CLANG3.6 compile the following code.

 struct A; std::vector<A> my_func(); //Definition of my_func is in some CPP file 

But throw errors for

 struct A; std::vector<A> v; 

And the argument for this is that the size of the vector will not change for the other type that it holds. See the following code snippet.

 struct B{int i; int j;}; struct C{int a,b,c;}; std::vector<B> pp; std::vector<C> qq; int main() { std::cout<<sizeof(pp)<<'\n'; std::cout<<sizeof(qq)<<'\n'; } 

Exit

 24 24 

But for std::vector<A> v it should also provide Allocator<A>() . And the distributor needs members of the struct A constructor like the constructor, copy constructor, destructor, etc. It is also important to note here pointer arithmetic for incomplete type is not allowed.

If you see errors released by CLANG, this clearly says the same thing.

 In file included from /tmp/gcc-explorer-compiler115920-68-1xsb8x7/example.cpp:2: In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/vector:64: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_vector.h:161:9: error: arithmetic on a pointer to an incomplete type 'A' - this->_M_impl._M_start); } ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_vector.h:253:7: note: in instantiation of member function 'std::_Vector_base<A, std::allocator<A> >::~_Vector_base' requested here vector() ^ 

Everything else is pretty straight forward.

The following is an example of typedef, so the compiler needs to know about size.

 using abc_vector = std::vector<abc>; 

So, the code structure in question is good to continue.

+2
source

All Articles