sub*_*ubi 11 c++ templates pointer-to-member
请考虑以下代码:
struct A { // a class we want to hide from the client code
int f();
int f(char);
int g();
};
struct B : A {}; // the interface class
// client code:
//
// It's natural to assume a member function of T should have
// a type of int (T::*)(), right?
template <typename T, int (T::*)()> struct F {};
// compiles, of course
F<A, &A::g> {};
// doesn't compile, because &B::g is not of type `int (B::*)()`, and no
// conversion is allowed here
F<B, &B::g> {};
// compiles, because &B::g is actually &A::g
//
// but this is not I want because the class hierarchy may be deep and it's
// not easy to know what A is.
F<A, &B::g> {};
Run Code Online (Sandbox Code Playgroud)
该片段struct<B, &B::g> {}无法编译,因为
&B::g是int (A::*)(),而不是int (B::*)();int (A::*)()到int (B::*)()是合法的和可行的,C++标准者禁用(!!)做为点对成员函数模板参数模板参数替换时任何转换.(严格来说,nullptr_t允许转换为.)因此,F<B, &B::g>无法匹配确切的定义,F并且无法编译.这很难过,因为class A可能是我们不想打扰的实现细节.
一个天真的黑客将是
template <typename T, T val> struct G {};
// at least compiles, and don't have to be aware of A
G<decltype(&B::g), &B::g> {};
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.
上面的hack不适用于重载的类方法.通常,重载可以通过static_cast来解决,但这需要我们知道&B :: f的确切类型 - 一个很好的鸡蛋和鸡蛋情况.
// won't compile since &B::f is ambiguous
G<decltype(&B::f), &B::f> {};
// won't compile just like F<B, &B::g>
G<decltype(static_cast<int(B::*)()>(&B::f)), &B::f> {};
// compiles, but require the knowledge of the type of &B::f
G<decltype(static_cast<int(A::*)()>(&B::f)), &B::f> {};
Run Code Online (Sandbox Code Playgroud)
像是G<decltype(static_cast<int(A::*)()>(&B::f)), &B::f> {};可怕的东西.
总结一下,问题是如何正确选择特定的重载并避免A在&B::f实际时提及基类&A::f.
有什么想法吗?
我找到了适合我要求的解决方法。希望对有需要的人有帮助。我被困了好几天了...
这个想法是使用函数模板来匹配特定的重载,然后将正确的类型传递给G. 间接层总是可以拯救世界。
template <typename T>
auto forward_pmf_with_signature( int(T::*pmf)() ) -> decltype(pmf);
G<decltype(forward_pmf_with_signature(&B::f)), &B::f> {}; // works
Run Code Online (Sandbox Code Playgroud)
G在没有意识到的情况下使用A并选择正确的过载,很酷。
现在新的问题是我发现G<decltype(forward_pmf_with_signature(&B::f)), &B::f>是多余的并且容易出错。使用宏USE_G(&B::f)来简化代码是微不足道的,但在我看来,以语义的方式进行简化并不容易,甚至不可能。