MSVC list initialization ICE when used with structs? - c++

This piece of code compiles well on gcc 8.1 and clang 6.0, but gives ICE on MSVC (both 2017 and 2018 pre-release):
#include <vector>
#include <string>
struct Data {
unsigned char data;
};
struct A {
std::string x;
Data y{255};
};
void f(std::vector<A> arg) {
}
int main() {
f(std::vector<A>{{"Test"}});
}
Clearly, I've run into yet another MSVC compiler bug.
But to be really sure: Does the above code conform to standard C++, or have I made an error as well?

Related

Different behavior of consteval in GCC and MSVC (not work)

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
}

Error C2079 'std::pair<Dummy<int>,Dummy<int>>::first' uses undefined class 'Dummy<int>'

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>{});
}

C++ - Errors when trying to insert class into map

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.

Clang++ Xcode 4.4 Non Static Member Initialization and Move constructor

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!

Problem replacing boost::bind with std::tr1::bind

I have the following code which compiles and runs fine under Visual Studio 2008 SP1.
#include <functional>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/utility.hpp>
class NoncopyableObject : public boost::noncopyable
{
public:
NoncopyableObject(int x) : x_(x) {}
int getValue() const {return x_;}
private:
int x_;
};
template<class F>
class MenuItemDispatcher
{
public:
MenuItemDispatcher(F f) : f_(f) { }
void operator ()(NoncopyableObject& w) const
{
// Invoke the functor
f_(w);
}
private:
typedef boost::function1<void,NoncopyableObject&> FUNC;
FUNC f_;
};
void MenuItem()
{
std::cout << "in MenuItem()\n";
}
template<class F>
MenuItemDispatcher<F> MakeMenuItemDispatcher(F f)
{
return MenuItemDispatcher<F>(f);
}
int main()
{
NoncopyableObject obj(7);
MakeMenuItemDispatcher(boost::bind(&MenuItem))(obj);
}
If I change the boost::bind to std::tr1::bind in main(), I get an error:
error C2248: 'boost::noncopyable_::noncopyable::noncopyable' : cannot access private member declared in class 'boost::noncopyable_::noncopyable'.
This diagnostic occurred in the compiler generated function 'NoncopyableObject::NoncopyableObject(const NoncopyableObject &)'
So it's trying to generate a copy constructor for NoncopyableObject. Anyone know why this might be so please? MenuItemDispatcher's call operator takes a reference to a NoncopyableObject, so I am struggling to see what's going wrong.
This appears to be a difference in how bind is implemented in MS Visual Studio (including 2010) and GNU gcc (I tested 4.4.1 and 4.5.2, both of which work the way you expected)
Consider the following code, given your definitions
auto b = boost::bind(&MenuItem);
NoncopyableObject obj(7);
b(obj); // OK in VS and GCC
replacing boost::bind with std::bind (I'm using 2010, the error message appears to be the same as in your 2008)
auto b = std::bind(&MenuItem);
NoncopyableObject obj(7);
b(obj); // compile error in VS 2010 SP1, OK in GCC
b(std::reference_wrapper<NoncopyableObject>(obj)); // OK in both
So, what happens is that MS's bind() makes a copy of its argument even if the argument is not going to be used, while boost's and GCC's bind() does not bother with that argument at all.
I was able to get your example to compile and run (on 2010) by changing the FUNC typedef to
typedef boost::function1<void, std::tr1::reference_wrapper<NoncopyableObject> > FUNC;