Было обнаружено действительно странное и неожиданное поведение clang 5 при переходе на С++ 17 и замену стандартного решения std::optional
на стандартное. По какой-то причине emplace()
был отключен из-за ошибочной оценки черты std::is_constructible
класса параметров.
Перед тем, как он воспроизведет, необходимо выполнить некоторые конкретные предпосылки:
#include <optional>
/// Precondition #1: T must be a nested struct
struct Foo
{
struct Victim
{
/// Precondition #2: T must have an aggregate-initializer
/// for one of its members
std::size_t value{0};
};
/// Precondition #3: std::optional<T> must be instantiated in this scope
std::optional<Victim> victim;
bool foo()
{
std::optional<Victim> foo;
// An error
foo.emplace();
/// Assertion is failed
static_assert(std::is_constructible<Victim>::value);
}
};
Пример Live на godbolt.org
Измените любое из предварительных условий и он скомпилируется, как и ожидалось. Есть ли какая-то неизвестная несогласованность в стандарте, которая заставляет clang отклонять этот код, будучи совместимым?
В качестве побочного примечания: GCC 7.1 и GCC 7.2 не имеют проблем с указанным выше кодом.
Отчет об ошибках: bugs.llvm.org