【发布时间】:2019-06-02 12:34:50
【问题描述】:
我对 C++ 中的简单反射机制有疑问。我想要一种模板类型,它应该以不同的成员函数指针作为模板参数表现不同:
[解决方案#1,按标准来说是不好的]
如果我有一个具有类类型及其成员函数指针的类模板,我不能专门化成员指针为空,因为我不能专门化“具有依赖类型的非类型模板参数”(请参阅:https://en.cppreference.com/w/cpp/language/partial_specialization参数列表 [5])
template<class O, void(O::*foo)() = nullptr>
struct p
{};
template<class O, void(O::*foo)()>
struct p<O, nullptr>
{};
[解决方案#2,GCC 问题]
如果我尝试专门研究一个推断的 constexpr 值,该值反映到成员指针,编译器会遇到不同的问题。 GCC8.2 x64 告诉我 nullptr == foo 表达式在上下文中不是常量:p<A, &A::f> j;。但是 ARM GCC8 说没关系。我认为这是一些内存布局问题,struct A 在模板引擎尝试评估具体函数指针时并不完整。
template<class O, void(O::*foo)() = nullptr, bool = nullptr == foo>
struct p
{};
template<class O, void(O::*foo)()>
struct p<O, foo, true>
{};
struct A
{
void f();
p<A, &A::f> j;
};
[解决方案#2 用法,MSVC 问题]
奇怪的是,MSVC 19.5 x86 上面的没问题,它还有另一个问题。它正在工作,而结构 A 是独立的,或者它继承自一个结构。但是当有两个基本结构(X,Y)时,它会因内部编译器错误而死。
template<class O, void(O::*foo)() = nullptr, bool = nullptr == foo>
struct p
{};
template<class O, void(O::*foo)()>
struct p<O, foo, true>
{};
struct X{};
struct Y{};
struct A : X, Y
{
void f();
p<A> i;
p<A, &A::f> j;
};
Clang7 可以很好地处理上述所有内容。
如果这是一种未定义的行为,谁能解释一下,或者标准中是否有关于这个主题的任何指南?
【问题讨论】:
-
请注意,与 C++17 相比,您可能拥有
template <auto foo = nullptr>,这可能会简化您的专业化和使用。 -
请不要给你的班级打电话
O!你确定能看出问题吗? -
您可能想要为 ICE 发布错误报告。