clang
clang copied to clipboard
get_pointer_v fails in c++1z mode
The following code compiles fine using -std=c++14
#include <reflexpr>
struct TestClass {
int member;
};
int main() {
auto ptr = std::meta::get_pointer_v<reflexpr(TestClass::member)>;
return 0;
}
However when using -std=c++1z
, the compilation fails
In file included from ReflTest.cpp:1:
include\reflexpr:524:2: error: non-type template argument is not a constant expression
__metaobject_get_pointer(__unwrap_id_v<T>)
^~~~~~~~~~~~~~~~~~~~~~~~
include\reflexpr:528:38: note: in instantiation of template class 'std::meta::get_pointer<std::__metaobject<8376711039260828486> >'
requested here
constexpr const auto get_pointer_v = get_pointer<T>::value;
^
ReflTest.cpp:8:27: note: in instantiation of variable template specialization 'std::meta::get_pointer_v' requested here
auto ptr = std::meta::get_pointer_v<reflexpr(TestClass::member)>;
^
include\reflexpr:524:2: note: non-literal type 'int TestClass::*' cannot be used in a constant expression
__metaobject_get_pointer(__unwrap_id_v<T>)
^
1 error generated.
Although I haven't tested this on another platform, I think it's Windows specific.
The member pointer type is being flagged as non-literal because it sees it as incomplete. This part of Type::isIncompleteType
shows that a member pointer can only be incomplete when compiling for the Microsoft ABI. In that case, it'll be incomplete if it's yet to receive an MSInheritanceAttr
. The attribute is set in Sema::RequireCompleteTypeImpl
.
When using regular member pointers (i.e. not through reflection): Sema::CreateBuiltinUnaryOp
calls Sema::CheckAddressOfOperand
, which specifically forces the inheritance attribute to be applied at this point. However this doesn't happen for member pointers produced by the reflection system, which is what causes the error. I suppose the fix would be to force application of the inheritance attribute in the same way (by calling Sema::isCompletetype
) wherever the reflection system makes these member pointers (I haven't looked at where that is yet).
It only fails in c++1z mode because it requires the parameter check to happen sooner. It happens to work in earlier std modes because the code below that ends up calling Sema::isCompleteType
anyway, which applies the attribute hence making the type complete.
Hi, thanks for the hint! I'll have a look at this ASAP.