I recently upgraded my Intel C++ compiler from v13.0.1 (aka 2013) to v14.0.0 (aka 2013 sp1). It looks as though the standard libraries that it uses have become more C++11 compliant. As part of that, std::locale::facet was changed from:
class locale::facet {
protected:
explicit facet (size_t refs = 0);
virtual ~facet();
private:
facet (const facet&); // not defined
void operator= (const facet&); // not defined
}
To:
class locale::facet {
protected:
explicit facet (size_t refs = 0);
virtual ~facet();
facet (const facet&) = delete;
void operator= (const facet&) = delete;
}
The key piece being the use of = delete to make it non-copyable. (Thanks to http://www.cplusplus.com/reference/locale/locale/facet/ for that side-by-side comparison.)
However, boost/date_time/date_facet.hpp uses this:
class date_facet : public std::locale::facet {
That's unchanged in both boost v1.48.0 and v1.54.0 (the two that I have installed in my environment).
date_facet doesn't appear to declare any copy constructor or operator=.
In my own code, I am using it to make class static constants to hold a time format. So in a header file I have this as part of a class definition:
static const boost::local_time::local_time_facet _MYFACET;
And in the matching source file I have this:
const boost::local_time::local_time_facet MyClass::_MYFACET = boost::local_time::local_time_facet("%Y/%m/%d %H:%M:%S.%f");
This code has worked for years and is unchanged.
Now, when I try to compile I get this error:
/usr/include/boost/date_time/date_facet.hpp(49): error #373: "std::locale::facet::facet(const std::locale::facet &)" (declared at line 409 of "/usr/include/c++/4.4.6/bits/locale_classes.h") is inaccessible
class date_facet : public std::locale::facet {
^
compilation aborted for MyFile.cpp (code 2)
Googling hasn't turned up anyone else talking about this problem, which makes me think that I'm just doing something stupid.
Anyone else encountered this?
Anyone have a solution?
My only idea is to explicitly add an = delete declaration to date_facet. I'll try that and supply my own answer if it works. But I really have no idea. (Edit: this idea was a failure, so don't try it.)
The reason for your troubles is that the =delete fires at compile-time in case you try to use it. Your existing code worked because the copy-constructor was required to be accessible (which is was), but it was optimized away by copy elision. The linker, who was supposed to catch the use of the copy-ctor therefore never complained and all seemed fine. That said, you might simply change your code to
const boost::local_time::local_time_facet MyClass::_MYFACET("%Y/%m/%d %H:%M:%S.%f");
and remove the need to an accessible (or even existing) copy-ctor.
Why can not you write simply
const boost::local_time::local_time_facet MyClass::_MYFACET("%Y/%m/%d %H:%M:%S.%f");
P.S. It seems that the early version of the compiler had a bug.:)
Related
I'm using /NODEFAULTLIB to disable CRT(C Runtime), however my constructor is not called, which ends up causing an error in std::map (Access violation) because it is not initialized properly, since std::map constructor it's not called.
Code compiled with LLVM 8.0.0, compiled in mode debug x86
class c_test
{
public:
c_test( int a ) // Constructor not called
{
printf( "Test: %i\n", a ); // Doesn't appear and breakpoint is not reached
}
void add( const std::string& key, const std::string& val )
{
_data[ key ] = val;
}
private:
std::map< std::string, std::string > _data;
};
c_test test{ 1337 };
int main()
{
test.add( "qwrqrqr", "23142421" );
test.add( "awrqw", "12asa1faf" );
return 1;
}
I've implemented my own functions new(HeapAlloc), delete(HeapFree), printf, memcpy, memmove, etc, and all are working perfectly, I have no idea why this happening.
Disabling the CRT is madness.
This performs crucial functions, such as static initialisation. Lack of static initialisation is why your map is in a crippled state. I would also wholly expect various parts of the standard library to just stop working; you're really creating a massive problem for yourself.
Don't reinvent little pieces of critical machinery — turn the CRT back on and use the code the experts wrote. There is really nothing of relative value to gain by turning it off.
I discovered the problem and solved, one guy from another forum said that I needed manually call constructors that are stored in pointers in .CRT section, I just did it and it worked perfectly
I just called _GLOBAL__sub_I_main_cpp function that calls my constructor and solved all my problems, thanks for the answers.
This code:
struct TToken
{
UnicodeString &DBIDs;
std::vector<TToken> T;
TToken(UnicodeString &DI) : DBIDs(DI) {}
void Append(void) {T.push_back(TToken(DBIDs));}
};
UnicodeString DI="25,40,55";
TToken T(DI);
if (T.DBIDs==DI) // if I comment out this comparison it works fine
....
generates the above compiler error (I'm using C++Builder 10.1 Berlin).
If I change the UnicodeString reference to a pointer, it all works as expected. Does anyone know why the reference generates the error?
By the way, is there an easier way of making DBIDs available to every created vector element instead of passing a pointer/reference all the way down the line? A static member is no good, and I did look at template expressions, but couldn't get an acceptable answer.
I was watching MVA's tutorial on C++ and the code I'm mentioning below is written by Kate not me. However she seems to get around with it without compiling showing any error but in my case I get the following error:
Error 1 error C2797: 'NamedRectangle::_name': list initialization
inside member initializer list or non-static data member initializer
is not implemented c:\users\abhimanyuaryan\documents\visual studio
2013\projects\kate demos\17
inheritance\inheritance\namedrectangle.h 12 1 Inheritance
Line 12 in the code is from my NameRectangle class which inherits from Rectangle class:
class NamedRectangle : public Rectangle
{
public:
NamedRectangle() { }
NamedRectangle(std::string initial_name, int initial_width, int initial_height)
: Rectangle{ initial_width, initial_height }, _name{ initial_name } //--> This line
{}
std::string get_name() const { return _name; }
private:
std::string _name;
};
when I remove std::string initial_name from constructor as well as _name{initial_name} the code compiles. Please explain me with not taking me as a higher standard experienced programmer. I started C++ yesterday only.
tl;dr: The solution in Kate's answer worked for the OP; the explanation is incorrect. The code in question is actually correct and does compile in VS2015. The error (in VS2013 Update 3) is a consequence of how MS handled a bug that was uncovered in VS2013 RTM (they didn't actually fix it with an update, but they did break some working code). It is fixed correctly in VS2015.
Your code works fine in VS2015. According to Microsoft, in VS2013,
Yes, we inserted these errors into the compiler in Update 3 because our implementation of non-static data member initialization was incomplete.
List/braced initialization in a member initialization list is also broken in VS2013. The problem with their implementation is illustrated best with a vector, which has an initializer_list constructor that should greedily match any initialization that uses braces with convertable arguments, but it fails to do so:
struct S {
S() : v1{1} {} // C2797, VS2013 RTM incorrectly calls 'vector(size_type)'
std::vector<int> v1;
std::vector<int> v2{1, 2}; // C2797, VS2013 RTM incorrectly calls
// 'vector(size_type, const int &)'
};
The compiler too readily falls back to normal overload resolution. Instead of using the std::initializer_list constructor, it calls the size_t constructor. As their comments indicate, this is wrong! So, because of their flawed implementation, Microsoft decided to disable the ability to use braced initialization in this context.
For a std::string s, there should be no issue because the right thing for s{"duh"} is to call std::string(const char*), but because of the flaw, MS gives an error anyway. The workaround is to explicitly use parenthesis in place of braces (or upgrade to VS2015), as stated in Kate's answer. But the correct reason for the error is as stated above.
This applies to Non-Static Data Member Initialization (NSDMI) as well as to initialization lists. This is explained more in this Visual C++ Team Blog. As for why VS2013 never got fixed:
We originally planned to fix this bug in an update to Visual Studio 2013, but from an engineering perspective, the right thing to do is to avoid another kludge and thoroughly address the handling of initialization. But overhauling compiler architecture is a massive task due to the amount of fundamental code that needs to be modified. We could not risk creating incompatibilities or large bug tails in an update, so a correct implementation of NSDMI could only be shipped in a major release.
Apparently, the fix made it into Visual Studio 2015, but will never be in an update to 2013.
There was a compiler change between the time James and I wrote the code we used for the MVA day and today. What's happening is that
_name{ initial_name }
is being interpreted as creating an initializer-list with one item in it and using that to initialize the member variable. Which you can't do.
The fix is to switch to round brackets:
_name(initial_name)
This is causing confusion for a number of people and I have at least one client for whom this broke working code.
I solve it.
class Namedrectangle : public Rectan
{
public:
Namedrectangle(){}
Namedrectangle(string intname, int init_width, int init_height)
: Rectan{ init_width, init_height }
{
this->_name=intname;************
}
string get_name() const
{
return _name;
}
private:
string _name;
};
I think İt can't initialize because variable can't find or load
Question is in bold below :
This works fine:
void process_batch(
string_vector & v
)
{
training_entry te;
entry_vector sv;
assert(sv.size() == 0);
...
}
However, this causes the assert to fail :
void process_batch(
string_vector & v
)
{
entry_vector sv;
training_entry te;
assert(sv.size() == 0);
...
}
Now I know this issue isn't shrink wrapped, so I'll restrict my question to this: what conditions could cause such a problem ? Specifically: variable initialization getting damaged dependant on appearance order in the stack frame. There are no malloc's or free's in my code, and no unsafe functions like strcpy, memcpy etc... it's modern c++. Compilers used: gcc and clang.
For brevity here are the type's
struct line_string
{
boost::uint32_t line_no;
std::string line;
};
typedef std::vector<boost::uint32_t> line_vector;
typedef std::vector<line_vector> entry_vector;
typedef std::vector<line_string> string_vector;
struct training_body
{
boost::uint32_t url_id;
bool relevant;
};
struct training_entry
{
boost::uint32_t session_id;
boost::uint32_t region_id;
std::vector< training_body> urls;
};
p.s., I am in no way saying that there is a issue in the compiler, it's probably my code. But since I am templatizing some code I wrote a long time ago, the issue has me completely stumped, I don't know where to look to find the problem.
edit
followed nim's suggestion and went through the following loop
shrink wrap the code to what I have shown here, compile and test, no problem.
#if 0 #endif to shrink wrap the main program.
remove headers till it compiles in shrink wrapped form.
remove library links till compiles in shrink wrapped form.
Solution: removing link to protocol buffers gets rid of the problem
The C++ standard guarantees that the following assertion will succeed:
std::vector<anything> Default;
//in your case anything is line_vector and Default is sv
assert(Default.size() == 0);
So, either you're not telling the whole story or you have a broken STL implementation.
OR: You have undefined behavior in your code. The C++ standard gives no guarantees about the behavior of a program which has a construct leading to UB, even prior to reaching that construct.
The usual case for this when one of the created objects writes beyond
its end in the constructor. And the most frequent reason this happens
in code I've seen is that object files have been compiled with different
versions of the header; e.g. at some point in time, you added (or
removed) a data member of one of the classes, and didn't recompile all
of the files which use it.
What might cause the sort of problem you see is a user-defined type with a misbehaving constructor;
class BrokenType {
public:
int i;
BrokenType() { this[1].i = 9999; } // Bug!
};
void process_batch(
string_vector & v
)
{
training_entry te;
BrokenType b; // bug in BrokenType shows up as assert fail in std::vector
entry_vector sv;
assert(sv.size() < 100);
...
}
Do you have the right version of the Boost libaries suited for your platform? (64 bit/32 bit)? I'm asking since the entry_vector object seems to be have a couple of member variables of type boost::uint32_t. I'm not sure what could be the behaviour if your executable is built for one platform and the boost library loaded is of another platform.
i have a little problem, and I am not sure if it's a compiler bug, or stupidity on my side.
I have this struct :
struct BulletFXData
{
int time_next_fx_counter;
int next_fx_steps;
Particle particles[2];//this is the interesting one
ParticleManager::ParticleId particle_id[2];
};
The member "Particle particles[2]" has a self-made kind of smart-ptr in it (resource-counted texture-class). this smart-pointer has a default constructor, that initializes to the ptr to 0 (but that is not important)
I also have another struct, containing the BulletFXData struct :
struct BulletFX
{
BulletFXData data;
BulletFXRenderFunPtr render_fun_ptr;
BulletFXUpdateFunPtr update_fun_ptr;
BulletFXExplosionFunPtr explode_fun_ptr;
BulletFXLifetimeOverFunPtr lifetime_over_fun_ptr;
BulletFX( BulletFXData data,
BulletFXRenderFunPtr render_fun_ptr,
BulletFXUpdateFunPtr update_fun_ptr,
BulletFXExplosionFunPtr explode_fun_ptr,
BulletFXLifetimeOverFunPtr lifetime_over_fun_ptr)
:data(data),
render_fun_ptr(render_fun_ptr),
update_fun_ptr(update_fun_ptr),
explode_fun_ptr(explode_fun_ptr),
lifetime_over_fun_ptr(lifetime_over_fun_ptr)
{
}
/*
//USER DEFINED copy-ctor. if it's defined things go crazy
BulletFX(const BulletFX& rhs)
:data(data),//this line of code seems to do a plain memory-copy without calling the right ctors
render_fun_ptr(render_fun_ptr),
update_fun_ptr(update_fun_ptr),
explode_fun_ptr(explode_fun_ptr),
lifetime_over_fun_ptr(lifetime_over_fun_ptr)
{
}
*/
};
If i use the user-defined copy-ctor my smart-pointer class goes crazy, and it seems that calling the CopyCtor / assignment operator aren't called as they should.
So - does this all make sense ? it seems as if my own copy-ctor of struct BulletFX should do exactly what the compiler-generated would, but it seems to forget to call the right constructors down the chain.
compiler bug ? me being stupid ?
Sorry about the big code, some small example could have illustrated too. but often you guys ask for the real code, so well - here it is :D
EDIT : more info :
typedef ParticleId unsigned int;
Particle has no user defined copyctor, but has a member of type :
Particle
{
....
Resource<Texture> tex_res;
...
}
Resource is a smart-pointer class, and has all ctor's defined (also asignment operator)
and it seems that Resource is copied bitwise.
EDIT :
henrik solved it... data(data) is stupid of course ! it should of course be rhs.data !!!
sorry for huge amount of code, with a very little bug in it !!!
(Guess you shouldn't code at 1 in the morning :D )
:data(data)
This is problematic. This is because your BulletFXData struct does not have it's own copy-ctor. You need to define one.
Two things jump out at me:
Is this a compiler bug
No. It is never a compiler bug. In twenty years I have seen enumerus complaints,
'it must be a compiler bug' only one has ever turned out to be a bug and that way
back with gcc 2.95 (nowadays gcc is solidly stable (as is dev studio))'
I built my own smart pointer.
Its a nice concept and a nice learning experience. But it is so much harder
to get correct than you think. Especially when you seem to be having trouble with
copy constructors
This is wrong The structure is copy constructed using itself as the object to be copied. Thus you are copy random data into itself.
:Look at comments to see what you should be using as parameters.
//USER DEFINED copy-ctor. if it's defined things go crazy
BulletFX(const BulletFX& rhs)
:data(data), // rhs.data
render_fun_ptr(render_fun_ptr), // rhs.render_fun_ptr
update_fun_ptr(update_fun_ptr), // rhs.update_fun_ptr
explode_fun_ptr(explode_fun_ptr), // rhs.explode_fun_ptr
lifetime_over_fun_ptr(lifetime_over_fun_ptr) // rhs.lifetime_over_fun_ptr
{
}
Of course at this point you may as well use the compiler generated version of the copy constructor as this is exactly what it is doing.