Унифицированная инициализация при ошибке списка инициализатора члена

Я получаю ошибку компиляции в этом коде С++ 11, но я не знаю почему. Это код:

#include <condition_variable>

class NonCopiableClass
{
    std::condition_variable condition_;
};

struct NonCopiableStruct
{
    std::condition_variable condition_;
};

class Test
{
 public:
    Test() : 
        myClass{},
        myStruct{}
    {};
 private:
    NonCopiableClass myClass;
    NonCopiableStruct myStruct;
};

Ошибка Visual Studio 2015 со следующей ошибкой:

ошибка C2280: 'std:: condition_variable:: condition_variable (const std:: condition_variable &)': попытка ссылки на удаленную функцию 1 > c:\program files (x86)\microsoft visual studio 14.0\vc\include\mutex (550): note: см. Объявление 'std:: condition_variable:: condition_variable'.

Если я изменяю Test constructor, чтобы не использовать стандартную инициализацию С++ 11 Struct, она компилируется ОК.

Test() : 
        myClass{},
        myStruct() // <--- CHANGE
    {};

Я не понимаю, почему для Struct type использует конструктор копирования, но Class кажется ОК. Это происходит только с Struct с не скопированными членами.

Я также отметил, что если я инициализирую Struct вне списка инициализаторов элемента Test Class, он работает:

int main()
{
    NonCopiableStruct a{};   
    return 0;
}

Любая идея Почему этот код не работает?. Что происходит под капотом? В чем разница между инициализацией myClass и myStruct?. Почему он не будет компилироваться, если он используется для члена класса initializer list, но хорошо ли я использую его снаружи? Я пробовал GCC, и, похоже, все в порядке.

Ответ 1

Это похоже на ошибку MSVC. Разница в том, что версия struct является агрегатом, а версия class не является (из-за спецификатора частного доступа по умолчанию).

Версия класса - это значение, инициализированное символом {}. Структурная версия инициализируется агрегатом. Соответствующий компилятор должен просто перечислить инициализацию condition_ с помощью {}, потому что вы не предоставили ему инициализатор.

Но MSVC, похоже, спотыкается о том, что члены агрегата являются копиями, инициализированными из соответствующего инициализатора в списке инициализаторов. Кажется, что нужно проверить копию c'tor, даже если она не должна ее использовать.

Это также подтверждается тем фактом, что он знает, что делать, когда объект того же типа инициализируется вне списка инициализаторов членов.