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

Я получаю ошибку компиляции этого кода C++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 ): примечание: см. объявление 'std::condition_variable::condition_variable'.

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

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

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

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

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

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


person Borja    schedule 11.01.2018    source источник
comment
Их вообще не нужно инициализировать.   -  person    schedule 11.01.2018
comment
Переключитесь на VS2017.   -  person    schedule 11.01.2018


Ответы (1)


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

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

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

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

person StoryTeller - Unslander Monica    schedule 11.01.2018