hi,
the code below generates the following behavior. cld someone please
help understand it?
1) clean project + build project generates build errors (see bottom)
2) build a second time, errors disappears, run: ok
3) uncomment [1] and comment [2], no problem
4) uncomment [3] and [4], also no problem
#ifndef A_IMPL_H_
#define A_IMPL_H_
#include <memory>
class A_impl{
public:
A_impl();
virtual ~A_impl(){};
virtual std::auto_ptr<A_implclone()const=0;
private:
A_impl& operator=(const A_impl&);
};
#endif /*A_IMPL_H_*/
#ifndef A_H_
#define A_H_
#include <memory>
//#include "A_impl.h" // [1]
class A_impl;//[2]
class A{
public:
A(const A_impl& impl_);
A(const A& o);
A& operator=(const A& rhs);
private:
A();
std::auto_ptr<A_implpimpl;
};
#endif /*A_H_*/
#ifndef AS_H_
#define AS_H_
#include <vector>
#include "A.h"
class As{
public:
As(
const std::vector<A>& sub_collec_
);
private:
std::vector<Asub_collec;//[3]
};
#endif /*AS_H_*/
#include "A.h"
#include "A_impl.h"
A::A(const A_impl& impl_):pimpl(impl_.clone()){};
A::A(const A& o):pimpl((o.pimpl)->clone()){};
A& A::operator=(const A& rhs){
if(&rhs!=this){
pimpl=rhs.pimpl->clone();
};
return *this;
};
#include "As.h"
As::As(
const std::vector<A>& sub_collec_
): sub_collec(sub_collec_){};//[4]
instantiated from 'void std::_Destroy(_Tp*) [with _Tp = A]'
testing_vector_pimpl A.h line 6 1191008360119 128231
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::__destroy_aux(_ForwardIterator, _ForwardIterator, __false_type)
[with _ForwardIterator = A*]' testing_vector_pimpl line 122
1191008360120 128232
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::_Destroy(_ForwardIterator, _ForwardIterator, std::allocator<_T2>)
[with _ForwardIterator = A*, _Tp = A]' testing_vector_pimpl line 182
1191008360120 128234
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::_Destroy(_ForwardIterator, _ForwardIterator) [with
_ForwardIterator = A*]' testing_vector_pimpl line 155 1191008360120
128233
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_vector.h instantiated from 'std::vector<_Tp, _Alloc>::~vector()
[with _Tp = A, _Alloc = std::allocator<A>]' testing_vector_pimpl line
272 1191008360120 128235 4 1593
er wrote:
hi,
the code below generates the following behavior. cld someone please
help understand it?
don't say generate behavior, I see that's compiler-time error, behavior
much more means that the code runs expectedly.
1) clean project + build project generates build errors (see bottom)
2) build a second time, errors disappears, run: ok
that's more about the compiler, not about C++ language, I know that VC6
has some problems here.
3) uncomment [1] and comment [2], no problem
4) uncomment [3] and [4], also no problem
#ifndef A_IMPL_H_
#define A_IMPL_H_
#include <memory>
class A_impl{
public:
A_impl();
virtual ~A_impl(){};
virtual std::auto_ptr<A_implclone()const=0;
private:
A_impl& operator=(const A_impl&);
};
#endif /*A_IMPL_H_*/
#ifndef A_H_
#define A_H_
#include <memory>
//#include "A_impl.h" // [1]
class A_impl;//[2]
class A{
public:
A(const A_impl& impl_);
A(const A& o);
A& operator=(const A& rhs);
dtor is produced by compiler, it's
~A() {}
where std::auto_ptr::~auto_ptr() is called, which delete A_impl*, but
A_impl is incomplete type, if we only use forward declaration here. A
solution, declaration A::~A, and define it it *A.cpp*, where you include
"A_impl.h", so, A_impl is complete type there.
private:
A();
std::auto_ptr<A_implpimpl;
};
#endif /*A_H_*/
#ifndef AS_H_
#define AS_H_
#include <vector>
#include "A.h"
class As{
public:
As(
const std::vector<A>& sub_collec_
);
private:
std::vector<Asub_collec;//[3]
};
#endif /*AS_H_*/
#include "A.h"
#include "A_impl.h"
A::A(const A_impl& impl_):pimpl(impl_.clone()){};
A::A(const A& o):pimpl((o.pimpl)->clone()){};
A& A::operator=(const A& rhs){
if(&rhs!=this){
pimpl=rhs.pimpl->clone();
};
return *this;
};
#include "As.h"
As::As(
const std::vector<A>& sub_collec_
): sub_collec(sub_collec_){};//[4]
instantiated from 'void std::_Destroy(_Tp*) [with _Tp = A]'
testing_vector_pimpl A.h line 6 1191008360119 128231
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::__destroy_aux(_ForwardIterator, _ForwardIterator, __false_type)
[with _ForwardIterator = A*]' testing_vector_pimpl line 122
1191008360120 128232
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::_Destroy(_ForwardIterator, _ForwardIterator, std::allocator<_T2>)
[with _ForwardIterator = A*, _Tp = A]' testing_vector_pimpl line 182
1191008360120 128234
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::_Destroy(_ForwardIterator, _ForwardIterator) [with
_ForwardIterator = A*]' testing_vector_pimpl line 155 1191008360120
128233
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_vector.h instantiated from 'std::vector<_Tp, _Alloc>::~vector()
[with _Tp = A, _Alloc = std::allocator<A>]' testing_vector_pimpl line
272 1191008360120 128235
--
Thanks
Barry
On 9 29 , 3 49 , er <erwann.rog...@gmail.comwrote:
hi,
the code below generates the following behavior. cld someone please
help understand it?
1) clean project + build project generates build errors (see bottom)
build error because you used undefined class A_impl (with [1]
commented and [2] uncommented at the first time).
2) build a second time, errors disappears, run: ok
I have no idea how can you run the program when build still error.
3) uncomment [1] and comment [2], no problem
When this done, class A_impl has been defined before you use it, of
course OK.
4) uncomment [3] and [4], also no problem
When this done, class A_impl is used only as a type (for pointer). It
needn't declare its detail, 'class A_impl;' is enough.
>
#ifndef A_IMPL_H_
#define A_IMPL_H_
#include <memory>
class A_impl{
public:
A_impl();
virtual ~A_impl(){};
virtual std::auto_ptr<A_implclone()const=0;
private:
A_impl& operator=(const A_impl&);};
#endif /*A_IMPL_H_*/
#ifndef A_H_
#define A_H_
#include <memory>
//#include "A_impl.h" // [1]
class A_impl;//[2]
class A{
public:
A(const A_impl& impl_);
A(const A& o);
A& operator=(const A& rhs);
private:
A();
std::auto_ptr<A_implpimpl;};
#endif /*A_H_*/
#ifndef AS_H_
#define AS_H_
#include <vector>
#include "A.h"
class As{
public:
As(
const std::vector<A>& sub_collec_
);
private:
std::vector<Asub_collec;//[3]};
#endif /*AS_H_*/
#include "A.h"
#include "A_impl.h"
A::A(const A_impl& impl_):pimpl(impl_.clone()){};
A::A(const A& o):pimpl((o.pimpl)->clone()){};
A& A::operator=(const A& rhs){
if(&rhs!=this){
pimpl=rhs.pimpl->clone();
};
return *this;};
#include "As.h"
As::As(
const std::vector<A>& sub_collec_
): sub_collec(sub_collec_){};//[4]
instantiated from 'void std::_Destroy(_Tp*) [with _Tp = A]'
testing_vector_pimpl A.h line 6 1191008360119 128231
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::__destroy_aux(_ForwardIterator, _ForwardIterator, __false_type)
[with _ForwardIterator = A*]' testing_vector_pimpl line 122
1191008360120 128232
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::_Destroy(_ForwardIterator, _ForwardIterator, std::allocator<_T2>)
[with _ForwardIterator = A*, _Tp = A]' testing_vector_pimpl line 182
1191008360120 128234
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::_Destroy(_ForwardIterator, _ForwardIterator) [with
_ForwardIterator = A*]' testing_vector_pimpl line 155 1191008360120
128233
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_vector.h instantiated from 'std::vector<_Tp, _Alloc>::~vector()
[with _Tp = A, _Alloc = std::allocator<A>]' testing_vector_pimpl line
272 1191008360120 128235
On Sep 29, 8:08 am, Barry <dhb2...@gmail.comwrote:
er wrote:
hi,
the code below generates the following behavior. cld someone please
help understand it?
don't say generate behavior, I see that's compiler-time error, behavior
much more means that the code runs expectedly.
1) clean project + build project generates build errors (see bottom)
2) build a second time, errors disappears, run: ok
that's more about the compiler, not about C++ language, I know that VC6
has some problems here.
3) uncomment [1] and comment [2], no problem
4) uncomment [3] and [4], also no problem
#ifndef A_IMPL_H_
#define A_IMPL_H_
#include <memory>
class A_impl{
public:
A_impl();
virtual ~A_impl(){};
virtual std::auto_ptr<A_implclone()const=0;
private:
A_impl& operator=(const A_impl&);
};
#endif /*A_IMPL_H_*/
#ifndef A_H_
#define A_H_
#include <memory>
//#include "A_impl.h" // [1]
class A_impl;//[2]
class A{
public:
A(const A_impl& impl_);
A(const A& o);
A& operator=(const A& rhs);
dtor is produced by compiler, it's
~A() {}
where std::auto_ptr::~auto_ptr() is called, which delete A_impl*, but
A_impl is incomplete type, if we only use forward declaration here. A
solution, declaration A::~A, and define it it *A.cpp*, where you include
"A_impl.h", so, A_impl is complete type there.
private:
A();
std::auto_ptr<A_implpimpl;
};
#endif /*A_H_*/
#ifndef AS_H_
#define AS_H_
#include <vector>
#include "A.h"
class As{
public:
As(
const std::vector<A>& sub_collec_
);
private:
std::vector<Asub_collec;//[3]
};
#endif /*AS_H_*/
#include "A.h"
#include "A_impl.h"
A::A(const A_impl& impl_):pimpl(impl_.clone()){};
A::A(const A& o):pimpl((o.pimpl)->clone()){};
A& A::operator=(const A& rhs){
if(&rhs!=this){
pimpl=rhs.pimpl->clone();
};
return *this;
};
#include "As.h"
As::As(
const std::vector<A>& sub_collec_
): sub_collec(sub_collec_){};//[4]
instantiated from 'void std::_Destroy(_Tp*) [with _Tp = A]'
testing_vector_pimpl A.h line 6 1191008360119 128231
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::__destroy_aux(_ForwardIterator, _ForwardIterator, __false_type)
[with _ForwardIterator = A*]' testing_vector_pimpl line 122
1191008360120 128232
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::_Destroy(_ForwardIterator, _ForwardIterator, std::allocator<_T2>)
[with _ForwardIterator = A*, _Tp = A]' testing_vector_pimpl line 182
1191008360120 128234
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::_Destroy(_ForwardIterator, _ForwardIterator) [with
_ForwardIterator = A*]' testing_vector_pimpl line 155 1191008360120
128233
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_vector.h instantiated from 'std::vector<_Tp, _Alloc>::~vector()
[with _Tp = A, _Alloc = std::allocator<A>]' testing_vector_pimpl line
272 1191008360120 128235
--
Thanks
Barry
declaring ~A() in .h and writing A::~A(){} in .cpp did solve my
problem. thanks!
On Sep 28, 9:49 pm, er <erwann.rog...@gmail.comwrote:
the code below generates the following behavior. cld someone please
help understand it?
1) clean project + build project generates build errors (see bottom)
2) build a second time, errors disappears, run: ok
3) uncomment [1] and comment [2], no problem
4) uncomment [3] and [4], also no problem
#ifndef A_IMPL_H_
#define A_IMPL_H_
#include <memory>
class A_impl{
public:
A_impl();
virtual ~A_impl(){};
virtual std::auto_ptr<A_implclone()const=0;
private:
A_impl& operator=(const A_impl&);};
#endif /*A_IMPL_H_*/
#ifndef A_H_
#define A_H_
#include <memory>
//#include "A_impl.h" // [1]
class A_impl;//[2]
class A{
public:
A(const A_impl& impl_);
A(const A& o);
A& operator=(const A& rhs);
private:
A();
std::auto_ptr<A_implpimpl;};
#endif /*A_H_*/
The line with std::auto_ptr<is undefined behavior (with the
code as written). According to the standard, you can only
instantiate a template in the standard library over a completely
defined type.
#ifndef AS_H_
#define AS_H_
#include <vector>
#include "A.h"
class As{
public:
As(
const std::vector<A>& sub_collec_
);
private:
std::vector<Asub_collec;//[3]};
#endif /*AS_H_*/
#include "A.h"
#include "A_impl.h"
A::A(const A_impl& impl_):pimpl(impl_.clone()){};
A::A(const A& o):pimpl((o.pimpl)->clone()){};
A& A::operator=(const A& rhs){
if(&rhs!=this){
pimpl=rhs.pimpl->clone();
};
return *this;};
#include "As.h"
As::As(
const std::vector<A>& sub_collec_
): sub_collec(sub_collec_){};//[4]
instantiated from 'void std::_Destroy(_Tp*) [with _Tp = A]'
testing_vector_pimpl A.h line 6 1191008360119 128231
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::__destroy_aux(_ForwardIterator, _ForwardIterator, __false_type)
[with _ForwardIterator = A*]' testing_vector_pimpl line 122
1191008360120 128232
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::_Destroy(_ForwardIterator, _ForwardIterator, std::allocator<_T2>)
[with _ForwardIterator = A*, _Tp = A]' testing_vector_pimpl line 182
1191008360120 128234
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_construct.h instantiated from 'void
std::_Destroy(_ForwardIterator, _ForwardIterator) [with
_ForwardIterator = A*]' testing_vector_pimpl line 155 1191008360120
128233
/usr/lib/gcc/x86_64-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_vector.h instantiated from 'std::vector<_Tp, _Alloc>::~vector()
[with _Tp = A, _Alloc = std::allocator<A>]' testing_vector_pimpl line
272 1191008360120 128235
I don't know exactly why the rebuild eliminates the error with
g++. With some other compilers, however, template
instantiations are stored in a repository; if the template is
successfully instantiated in another translation unit, then the
rebuild will work.
But it doesn't really matter. You have undefined behavior, and
you should fix it.
--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Icosahedron |
last post by:
I've been going through some old code trying to clean it up
and rearchitect it based on more modern C++ idioms. In the
old code I often used the Pimpl idiom on a class by class
basis, creating...
|
by: Asfand Yar Qazi |
last post by:
Hi,
Now that GCC 3.4 has precompiled headers, I'm thinking I can stop
using pimpls to speed up development time, as it may make life
easier (declaring pimpls takes a long time...)
What are...
|
by: Peteris Krumins |
last post by:
Hello!
I was playing around pimpl idiom and discovered that there is a problem
with it if a class member template function exists which has to access
private data, since only the forward...
|
by: Edward Diener |
last post by:
Because 'friend' is not recognized in MC++, using the pImpl idiom in MC++
classes seems nearly impossible. Normally a pImpl class is a 'friend' to the
class for which it supplies the private...
|
by: red floyd |
last post by:
It seems that the use of auto_ptr<> is discouraged in many places in
favor of boost::shared_ptr<> (or tr1::shared_ptr<>). But consider a
PIMPL idiom, where there is a strict 1-1 relationship...
|
by: Asfand Yar Qazi |
last post by:
Hi,
I'm creating a library where several classes are intertwined rather tightly.
I'm thinking of making them all use pimpls, so that these circular
dependancies can be avoided easily, and I'm...
|
by: Daniel Lidström |
last post by:
Hello!
I have just discovered a way to use the private implementation idiom
(pimpl), without the overhead of dynamic memory allocation. For those of
you who don't know what this is, Wikipedia...
|
by: Graham Reitz |
last post by:
What are good strategies for selecting, either at run-time or compile
time, various pimpl'ed implementations? While retaining the ability
to switch implementations without recompiling.
Boost...
|
by: Ralf Goertz |
last post by:
Hi,
the following templated code doesn't compile. It gives the error:
template_it.cc:17: error: type 'std::vector<Derived1<T>*,
std::allocator<Derived1<T>*' is not derived from type...
|
by: DolphinDB |
last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation.
Take...
|
by: ryjfgjl |
last post by:
ExcelToDatabase: batch import excel into database automatically...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: jfyes |
last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
|
by: ArrayDB |
last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
|
by: PapaRatzi |
last post by:
Hello,
I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
|
by: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
by: Shællîpôpï 09 |
last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
|
by: Faith0G |
last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
| |