为通用引用和指向成员的指针推导出冲突类型

Deduced conflicting types for universal reference and pointer to member

我想要这样的功能:

template<typename C, typename T>
void foo(C &&aclass, T (C::*const memberFunc)(unsigned)) {

}

参数是(因为C/C++类型语法是心智的):

这种方法可行,但是如果我使用左值引用作为第一个参数调用它,我会收到如下错误:

candidate template ignored: deduced conflicting types for parameter 'C' ('MyClass &' vs. 'MyClass')

据我了解,它是从第一个和第二个参数推导C,但是得出不同的推导并感到困惑。

根据 this answer 你可以让它只对第一个参数进行推导,并以某种方式在第二个参数上使用 typename 关键字。但是当我确实希望它推断出参数中的一种类型(T)而不是另一种类型(C)时,我无法计算出执行此操作的语法。

This answer 也有帮助,但他们通过根本不使用 C 的引用来解决它,在那种情况下 同样有效,但是我的没有。

这可能吗?

实际上,我刚刚发现将通用参考重载转发到 l-value 参考版本是可行的。虽然不是特别优雅;我觉得应该有更好的方法。

template<typename C, typename T>
void foo(C &aclass, T (C::*const memberFunc)(unsigned)) {
  // Code goes here.
}

template<typename C, typename T>
void foo(C &&aclass, T (C::*const memberFunc)(unsigned)) {
  foo(aclass, memberFunc);
}

对于左值 C 将被推断为第一个参数的 lvalue-reference 类型(即 MyClass & 对于您的情况),这是 [=16= 的预期行为] 在第二个参数中使用 C 时,例如

template<typename C, typename T>
void foo(C &&aclass, T (std::remove_reference_t<C>::*const memberFunc)(unsigned)) {

}

正如@Quentin 指出的那样,使用 std::remove_reference 还引入了 non-deduced context,这将防止从第二个参数推导出 C