Open 4706ef27-75ea-42f3-88fa-731e80a74b18 opened 3 years ago
Interesting: the bad instantiation of is_constructible
https://godbolt.org/z/KbjYoG84a
So it looks like the compiler divergence here is because GCC declares the copy constructor lazily whereas Clang happens to declare it eagerly in this case.
I don't know the answer off-hand. I think this is probably undefined, but it's a reasonable thing to expect to work. I always find it surprising that nested types are not complete until the outer type is complete, rather than after the }; of their class body.
I tend to think this should work even if the standard doesn't allow it today.
This is bizarre, but I think it's not a Clang bug.
The problem here is that the libstdc++ implementation of optional
Now, because querying is_constructible
Ultimately, the problem is that (libstdc++'s) optional
Interestingly, if you attempt to default-construct an Outer::Inner before the optional
https://godbolt.org/z/v463bE5hh
I'm not sure why GCC doesn't observe the same result without the explicit preceding use of Outer::Inner::Inner().
+Jonathan Wakely, who might be able to shed some light on whether this is a bug in libstdc++ or whether this kind of example is violating the standard library's type completeness rules, or if my analysis is incorrect.
@llvm/issue-subscribers-clang-frontend
Author: None (4706ef27-75ea-42f3-88fa-731e80a74b18)
Confirmed on post-18 trunk: https://godbolt.org/z/5xqn1raq8
Extended Description
Code sample:
https://godbolt.org/z/jKoG9a7e4
In the above, the
emplace()
call causes an error, stating that the class (Outer::Inner
) does not have a constructor that matches the arguments. Note that this is specifically an issue in combination with libstdc++'s impl of std::optional; libc++ (since clang 9) seems to work (though prior to clang 9 it generates the same error).If you do
std::optional<Outer::Inner>
, it also fails (though it will succeed if you remove theinner
member).If you change
int a = 0
toint a
(without the default value), it will succeed.If you add an
Inner() = default
, it still fails, however addingInner() {}
will make it succeed.This may be loosely related to bug 15886.