I am using Xcode 4.4 with mountain lion. I can't seems to understand why non-static member initalization in templates invokes a move constructor for the variable. Is there anyway to overcome this error?
Example Code:
#include <iostream>
#include <atomic>
//
// This class can compile
//
class Working
{
public:
int GetValue() { return value_; }
private:
std::atomic<int> value_{0};
};
//
// This class cannot compile
//
template <typename Ty1>
class NotWorking
{
public:
int GetValue() { return value_; }
private:
std::atomic<int> value_{0}; // <---- error here
};
int main(int argc, const char * argv[])
{
Working working;
NotWorking<int> not_working;
return 0;
}
Xcode 4.4 and Clang throws the error in that line saying:
"Copying member subobject of type 'std::atomic<int>' invokes deleted constructor"
This looks like a clang bug on the open source svn trunk repository. Could you submit a bug report against clang here: http://llvm.org/bugs/ ?
Thanks!
Related
In the code below, class B contains an array of member class class A.
B::A has one member bool and one member std::thread.
The code below compiles fine:
// main.cpp
#include <mutex>
#include <thread>
class B {
public:
B();
private:
class A {
public:
A( const bool& b ) : b_( b ) {}
bool b_;
std::thread thread_;
} a_[2];
};
B::B() : a_{ { false }, { false } } { }
int main( int argc, char* argv[] ) {
B b;
return 0;
}
$ g++ --version && g++ -g ./main.cpp
g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$
Why does introducing a std::mutex to B::A introduce the following compile error?
// main.cpp
#include <mutex>
#include <thread>
class B {
public:
B();
private:
class A {
public:
A( const bool& b ) : b_( b ) {}
bool b_;
std::mutex mutex_; // I break compilation!
std::thread thread_;
} a_[2];
};
B::B() : a_{ { false }, { false } } { }
int main( int argc, char* argv[] ) {
B b;
return 0;
}
$ g++ -g ./main.cpp
./main.cpp: In constructor ‘B::B()’:
./main.cpp:21:35: error: use of deleted function ‘B::A::A(B::A&&)’
B::B() : a_{ { false }, { false } } { }
^
./main.cpp:11:9: note: ‘B::A::A(B::A&&)’ is implicitly deleted because the default definition would be ill-formed:
class A {
^
./main.cpp:11:9: error: use of deleted function ‘std::mutex::mutex(const std::mutex&)’
In file included from /usr/include/c++/6/mutex:44:0,
from ./main.cpp:2:
/usr/include/c++/6/bits/std_mutex.h:97:5: note: declared here
mutex(const mutex&) = delete;
^~~~~
If I correctly understand the compile error, it's complaining that an instance of B::A cannot be created without explicit construction of B::A::mutex_. But if this is true, I don't understand why this should be necessary: std::mutex has a default constructor, so doesn't need any constructor arguments, as demonstrated below:
// main.cpp
#include <mutex>
int main( int argc, char* argv[] ) {
std::mutex mutex[10];
return 0;
}
Please help me understand the nature of the above compile error, and what an appropriate fix might be.
Update: #Jarod42 and #chris seem to have discovered this is a compiler bug. I'm updating the question to ask if anyone could explain the nature of this bug -- initiaizing member array-of-object elements seems like such a simple and foundational thing. What type of objects trigger this bug and why? I can't imagine this could be a universal/easily reproducible problem...?
Update: A not-great workaround seems to be making B::A::A an empty constructor and initializing B::A::b_ with an rvalue. :(
// main.cpp
#include <mutex>
#include <thread>
class B {
public:
B();
private:
class A {
public:
A() : b_( false ) {}
bool b_;
std::mutex mutex_;
std::thread thread_;
} a_[2];
};
B::B() { }
int main( int argc, char* argv[] ) {
B b;
return 0;
}
$ g++ -g ./main.cpp
$
The apparent, likely cause of the bug is a subtle difference between copy-initialization and copy-list-initialization:
struct A {
A(int);
A(A&&)=delete;
} a=1, // error: not movable
b=A(1), // error
c={1}, // OK, no temporary constructed
d[]={1}, // error
e[]={A{1}}, // error
f[]={{1}}; // OK (the compiler bug)
Here a bare 1 is converted to a temporary A which cannot be copied/moved, whereas {1} is used to initialize the ultimate A despite the term “copy”. This distinction vanishes in C++17, where initialization from a prvalue (as for b or a after conversion) invokes only the prvalue’s constructor (“mandatory copy elision”).
The issue also couldn’t arise prior to C++11, since non-static array members could only be default- or value-initialized. (={} was also considered normal copy-initialization then and didn’t apply to class objects at all.) This is why your workaround worked, and the gradual adoption of the new initializers is probably why the compiler bug lasted as long as it did.
Note that, despite the error mentioning std::mutex’s deleted copy constructor, it is its non-movability that matters (as indicated by the B::A::A(B::A&&)), which is how it differs from std::thread.
Consider the following code:
#include <cstdint>
#include <vector>
class ClassT
{
public:
consteval static size_t GetSize()
{
return sizeof(int);
}
void Resize()
{
_Data.resize(GetSize(), 0);
}
std::vector<uint8_t> _Data;
};
int main()
{
ClassT Object;
Object.Resize();
return 0;
}
GCC compiles it successfully, but MSVC gives the following error:
error C7595: 'ClassT::GetSize': call to immediate function is not a constant expression
Am I missing something? Or is it really an MSVC bug?
Compilers version: x86-64 gcc 10.2 and x64 msvc v19.28. (Link to godbolt)
This looks like an MSVC bug. It might even be the same as this existing one- #1224555.
Minimal example:
consteval int test() { return 0; }
int main() {
return test(); // error C7595: 'test': call to immediate function is not a constant expression
}
The following code snippet compiles just fine with GCC 9.1 and Clang 6.0 under C++11/14/17 standards, but refuses to compile with Visual Studio 2019. I can change the return of getDummies() to auto and VS will compile with C++14/17 standards, but this breaks C++11 compatibility on all compilers, which I need to keep.
#include <cstdlib>
#include <utility>
template<typename T>
class Dummy
{
public:
//static auto getDummies() // Works but breaks C++11 compatibility
static std::pair<Dummy<int>, Dummy<int>> getDummies()
{
return std::make_pair(Dummy<int>{}, Dummy<int>{});
}
};
int main()
{
auto dummies = Dummy<int>::getDummies(); // Error C2079
return EXIT_SUCCESS;
}
The class Dummy is not fully defined at the point that the getDummies() function is defined, inside the class.
You can declare the function in the class then define it outside the class, like:
template<typename T>
class Dummy
{
public:
static std::pair<Dummy<int>, Dummy<int>> getDummies();
};
template<typename T>
std::pair<Dummy<int>, Dummy<int>> Dummy<T>::getDummies()
{
return std::make_pair(Dummy<int>{}, Dummy<int>{});
}
I have a map like so map<string, unique_ptr<Base>> variables and I am trying to insert data into the map variables.insert(make_pair("foo", new Int(10))) but I am getting to following errors:
error: no matching function for call to ‘std::map<std::__cxx11::basic_string<char>, std::unique_ptr<Base>>::insert(std::pair<const char*, Int*>)’
variables.insert(make_pair("test", new Int(10)));
error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
template<typename _Pair, typename = typename
This is my code:
class Base {
public:
Base() {};
virtual ~Base() {};
};
class Int : public Base {
public:
Int(int i) {
this->i = i;
}
Int operator=(int i) {
this->i = i;
}
int i;
};
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", new Int(10)));
}
I think I need a fresh pair of eyes to look at this I'm not sure what this issue is, thanks!
Edit
I'm trying to make a heterogeneous map and there's a class for each data type. But I still get the same error no matter how many there are.
Note: This answer only applies to older versions of the main three compilers:
GCC: Applies to 5.3.1 or earlier. May apply to any version earlier than 6.1.0, but I haven't tested this.
Clang: Applies to 3.7.1 or earlier. May apply to any version earlier than 3.8.0, but I haven't tested this.
Visual Studio: Applies to 19.00.23506.0 or earlier. May apply to any version earlier than 19.00.23720.0, but I haven't tested this.
Conversely, if you have GCC 6.1.0 or later, Clang 3.8.0 or later, or Visual Studio 19.00.23720.0 or later, the original code should compile as is, without either of the modifications suggested in this answer.
[Thanks goes to AndyG for pointing out that it works with later versions of GCC & Clang.]
The problem appears to be that it isn't creating your unique_ptr from your raw pointer.
If you can use C++14, try std::make_unique().
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", make_unique<Int>(10)));
}
If you can't, then try something like this:
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", unique_ptr<Int>(new Int(10))));
}
Interestingly, I noticed a slight difference in how different compilers handle this. Using the following slightly modified version of your code as a test program:
#include <map>
#include <memory>
#include <iostream>
class Base {
public:
Base() {};
virtual ~Base() {};
};
class Int : public Base {
public:
Int(int i) {
this->i = i;
}
Int& operator=(int i) {
this->i = i;
// You forgot to return something.
return *this;
}
int i;
};
void set() {
using namespace std;
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", new Int(10)));
// C++14:
// variables.insert(make_pair("test", make_unique<Int>(10)));
// C++11:
// variables.insert(make_pair("test", unique_ptr<Int>(new Int(10))));
// Cheap hack for testing.
cout << static_cast<Int*>(variables["test"].get())->i << endl;
}
int main() {
set();
}
Most compilers* will fail to compile this, unless the initial line is commented out and either of the fixes is uncommented. However, the online MSVC compiler seemed to be able to compile it fine, without needing to uncomment either of the lines. Curiously, the version of MSVC available on Rextester failed to compile it without uncommenting one of the two lines.
* Tested online, with TutorialsPoint GCC, MSVC 2015 online, and Rextester Clang, GCC, and MSVC.
Using clang (3.5.1) with address sanitizer on my program using boost (1.56) I got:
boost/serialization/singleton.hpp:132:13: runtime error: reference binding to null pointer
The example is:
#include<boost/serialization/singleton.hpp>
#include <string>
#include <iostream>
class Foo{
private:
std::string bar = "Hello World";
public:
void print() const{
std::cout << bar << std::endl;
}
};
int main(){
boost::serialization::singleton<Foo> test;
test.get_const_instance().print();
}
Then I do:
compilation
clang++ -I/boost/1_56_0/gcc-4.8.2/include/ -fsanitize=address,undefined -std=c++11 test.cpp
output
./a.out:
boost/1_56_0/gcc-4.8.2/include/boost/serialization/singleton.hpp:132:13: runtime error: reference binding to null pointer of type 'const Foo'
Hello World
Looking at the code, I am confused by the role of the reference instance in the class singleton. It looks like undefined behaviour.
Do you get it?
template<class T>
bool detail::singleton_wrapper< T >::m_is_destroyed = false;
} // detail
template <class T>
class singleton : public singleton_module
{
private:
BOOST_DLLEXPORT static T & instance;
// include this to provoke instantiation at pre-execution time
static void use(T const &) {}
BOOST_DLLEXPORT static T & get_instance() {
static detail::singleton_wrapper< T > t;
// refer to instance, causing it to be instantiated (and
// initialized at startup on working compilers)
BOOST_ASSERT(! detail::singleton_wrapper< T >::m_is_destroyed);
use(instance); // That's the line 132
return static_cast<T &>(t);
}
public:
BOOST_DLLEXPORT static T & get_mutable_instance(){
BOOST_ASSERT(! is_locked());
return get_instance();
}
BOOST_DLLEXPORT static const T & get_const_instance(){
return get_instance();
}
BOOST_DLLEXPORT static bool is_destroyed(){
return detail::singleton_wrapper< T >::m_is_destroyed;
}
};
I wasn't able to get the (address?) sanitizer working in my Xcode 6 environment. But I did trace through the program with the debugger. line 132 of singleton.hpp contains the line
use(instance);
where the value of instance has the (uninitialized value of zero). This might be considered an error by the sanitizer, but use(...) is an empty function. It is only included to guarantee that the singleton is called before main. If this isn't included, compile for release may optimize away the pre-main invocation and the class may not function as intended. So I would call this an over zealous behavior of the sanitizer. Or maybe the sanitizer could be considered not smart enough to trace one more level deep. or... .