1

I have compilers:
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
Microsoft Visual Studio 2015 ver. 14.0. (Visual C++ 2015)

Source code:

#include <queue>

class C
{
};


class B
{
public:
  // assignment and copy prohibited
  B(const B&) = delete;
  B& operator=(const B&) = delete;

  B(int v1, int v2) : m_V1(v1), m_V2(v2) {}

private:
  int m_V1;
  int m_V2;
  std::queue<C> m_Queue;
};

class A
{
public:
  // assignment and copy prohibited
  A(const A&) = delete;
  A& operator=(const A&) = delete;

  A(int p1, int p2) : arrB{ {p1+1, p2+2}, {p1+3, p2+4}, {p1+5, p2+6} } { }

private:
  B arrB[3];
};

1) If I use g++ with

std::queue<C> m_Queue;

I get the following error:

make
g++ -std=c++11 -c test.cpp
test.cpp: In constructor ‘A::A(int, int)’:
test.cpp:29:70: error: use of deleted function ‘B::B(const B&)’
   A(int p1, int p2) : arrB{ {p1+1, p2+2}, {p1+3, p2+4}, {p1+5, p2+6} } { }
                                                                      ^
test.cpp:11:3: error: declared here
   B(const B&) = delete;
   ^
make: *** [test.o] Error 1

2) If I use g++ and comment the line

//std::queue<C> m_Queue;

or I use both variants (commented and not) with Microsoft Visual Studio 2015 I don't get any errors.

Why?

Update:
List-initialization uses direct-list-initialization or copy-list-initialization.

8.5.4 List-initialization
1 List-initialization is initialization of an object or reference from a braced-init-list. Such an initializer is called an initializer list, and the comma-separated initializer-clauses of the list are called the elements of the initializer list. An initializer list may be empty. List-initialization can occur in direct-initialization or copyinitialization contexts; list-initialization in a direct-initialization context is called direct-list-initialization and list-initialization in a copy-initialization context is called copy-list-initialization.

But I do not understand what sort of initialization to be used in my case. I supposed that should be used direct-list-initialization in accordance with http://en.cppreference.com/w/cpp/language/list_initialization

Update 2:

8.5.1 Aggregates [dcl.init.aggr]
1 An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

When an aggregate is initialized by an initializer list, as specified in 8.5.4, the elements of the initializer list are taken as initializers for the members of the aggregate, in increasing subscript or member order. Each member is copy-initialized from the corresponding initializer-clause.

An aggregate is an array and Each member is copy-initialized - answer?
But this does not explain why compiles without errors when commenting on the line:

//std::queue<C> m_Queue;
Elija
  • 91
  • 6
  • Try initializing the `std::queue m_Queue;` as empty with curly brackets in `B`'s ctors initializer list. – Nowhere Man Apr 06 '16 at 17:36
  • g++ 5.2 likewise rejects the code when `m_Queue` is present and accepts it when `m_Queue` is commented out. clang++ 3.7, like VC++ 2015, accepts the code regardless. Furthermore if `B` is given a copy constructor that prints an I-am-being-called note, g++ compiles the code and a test program will show that this copy-constructor *is not called* in `A(int p1, int p2)`. – Mike Kinghan Apr 06 '16 at 19:39
  • @NowhereMan I tried. It does not change anything. – Elija Apr 07 '16 at 09:54

1 Answers1

0

Using the code provided I was unable to reproduce your strange behavior with g++ regarding the commenting/uncommenting of the queue declared in B. I get the same error on g++ whether the queue is commented out or not.

However, the compilation error that you are getting is the same as I get in my test of your code. This error results from the fact that you have explicitly deleted B's copy constructor. The error message points directly at B's copy constructor: B(const B&) = delete;

See this answer here for more details: https://stackoverflow.com/a/14543600/1456187

As to the second part of your question I can only hazard a guess since I do not have a copy of the Microsoft compiler handy. My best guess is that the Microsoft compiler allows the initialization of the array of Bs because they are being constructed in place. Although, this would seem to fly in the face of the standard as of the '03 spec.

Community
  • 1
  • 1
mwood
  • 1
  • 3