A really strange and unexpected behaviour of clang 5 was detected when switching to c++17 and replacing custom std::optional
solution with the standard one. For some reason, emplace()
was being disabled due to faulty evaluation of a std::is_constructible
trait of the parameter class.
Some specific preconditions must be satisfied before it reproduces:
#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 example on godbolt.org
Change any of the preconditions and it compiles as expected. Is there some unknown inconsistency in the standard that makes clang reject this code while being compliant?
As a side note: GCC 7.1 and GCC 7.2 have no problem with the above code.
Bug report at: bugs.llvm.org