无法从 FieldType* 推断出 T* 的模板参数(仅限 Visual C++)

could not deduce template argument for T* from FieldType* (Visual C++ only)

此代码在 g++ (Coliru), but not Visual C++ (rextester) 上编译正常 - 在线和我的桌面。

它是一个更大的 Visual Studio 2015 项目的简化版本。

class AAA{
    public: template<class T> static T*  test(T* hqi){
        return hqi;
    }
};
class TTT3{ 
    public: int d;   //In real case, it is some class, but same error nonetheless.
    decltype(AAA::test(&d)) dfd=AAA::test(&d);  //<-- error only Visual C++
};
int main(){
    int b;
    decltype(AAA::test(&b)) dfd=AAA::test(&b);  //OK for boths
}

'T *AAA::test(T *)': could not deduce template argument for 'T ' from 'int TTT3:: '

问题

这对我来说似乎无效,因为

中的第一个 &d
decltype(AAA::test(&d)) dfd=AAA::test(&d);

是在成员初始值设定项之外对 this 的隐式使用。我在标准中找不到任何例外,使 thisdecltype 中隐式使用有效,而且如果将 &d 替换为显式 &this->d,所有三个主要编译器都会抱怨.

不幸的是,我没有看到任何简单的解决方法,除非您替换 d 的实际类型或为其创建一个 typedef。

这是一个 Visual Studio 特定的错误。按照标准:

[expr.unary.op/4]

A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses. [ Note: That is, the expression &(qualified-id), where the qualified-id is enclosed in parentheses, does not form an expression of type “pointer to member”. Neither does qualified-id, because there is no implicit conversion from a qualified-id for a non-static member function to the type “pointer to member function” as there is from an lvalue of function type to the type “pointer to function” ([conv.func]). Nor is &unqualified-id a pointer to member, even within the scope of the unqualified-id's class. — end note ]

粗体文本是 VC++ 出于某种原因在 decltype 中没有正确执行的内容。由于希望 Microsoft 修复它是一种愚蠢的希望,您可以做的另一种解决方法是添加以下重载:

template<class C, typename T>
static T* test(T C::*);

Live Example

可能在检查 VC++ 的 #ifdef/#endif 块中。不定义它可以防止它在未评估的上下文(例如 decltype)之外被静默地选取,尽管只有 link 时间错误。