Ошибка компиляции в Visual C ++ - PullRequest
0 голосов
/ 14 мая 2018

Любая причина, почему это не компилируется в Visual Studio C ++? Я использую Visual Studio 2017 15.7.1. Компилируется в clang и g ++:

#include <utility>
#include <vector>

struct Foo {
    Foo(int x) {}
    Foo(Foo const& b) {}
};

struct Bar {
    template <class... Args>
    Bar(Args&&... args)
        : foo(std::forward<Args>(args)...) {}

    Foo foo;
};

void test() {
    std::vector<Bar> v;
    v.emplace_back(123);
}

Ошибка error C2664: 'Foo::Foo(const Foo &)': cannot convert argument 1 from 'Bar' to 'int'

См. https://godbolt.org/g/bKb34v

РЕДАКТИРОВАТЬ: Я представил этот вопрос здесь: https://developercommunity.visualstudio.com/content/problem/252470/perfect-forwarding-compiler-bug.html

1 Ответ

0 голосов
/ 15 мая 2018

Это ваша ошибка, а не MSVC.

  1. Foo Конструктор копирования не noexcept и не имеет конструктора перемещения.
  2. Barнеявно объявленный конструктор перемещения также не является noexcept, потому что ему нужно вызвать вышеупомянутый конструктор копирования для Foo члена данных.
  3. emplace_back может перераспределить, и, поскольку Bar выглядит копируемым, это перераспределениескопирует существующие элементы, чтобы сохранить строгую гарантию безопасности исключений.
  4. Это копирование может быть выполнено, в зависимости от реализации, из const или не const Bar lvalue.
  5. Ваш шаблон конструктора без ограничений копирует из неконстантного Bar lvalue.
  6. Далее следуют взрывы и фейерверки.

Исправление состоит в том, чтобы ограничить шаблон конструктора так, чтобы он нене угоняйНапример:

template <class... Args, 
          class = std::enable_if_t<std::is_constructible_v<Foo, Args...>>>
Bar(Args&&... args)
    : foo(std::forward<Args>(args)...) {}
...