带有指向成员函数指针的模板 => VC++ 2017 和 gcc 5.1 的不同错误消息

Template with pointer to member function => different error messages with VC++ 2017 and gcc 5.1

我被以下代码困住了,非常感谢任何建议

template <typename T, class U>
class A {
public:
    // Pointer to member function of U
    typedef void (U::*MemberPtr)(T);
    // Constructor
    Action(std::string action_name, MemberPtr func) {
        this->fPtr = func;
    } 
    // Invoke member function of U passed in constructor
    void invoke(T argument) {
        fPtr(argument); // <-- VC++ error C2064: Expression does not evaluate to a function call, ok for gcc  (Q1)
    }

private:
    MemberPtr fPtr;

以上模板用于class'C'

class C; // forward decl

class C {
    void dummyDbl(double arg);

    Action<double, C> dblAction = Action<double, C>("x", &C::dummyDbl);
    // gcc (5.1.0 )complains: (VS 2017 is fine with that) (Q2)
    // Action<double, C>("x", &C::dummyDbl);
    //                ^
    // error: expected unqualified-id before '>' token

我对听众的问题是

  1. 为什么编译器 (VC++ 2017) 抱怨函数调用,而 gcc 没有问题(请参阅问题 1)?我错过了什么?
  2. 知道为什么 gcc 会引发错误,而 VC++ 对于 decl (Q2) 没问题吗?
  3. 是否有机会 省略第二个模板参数 但将范围限制为给定 class 的成员函数(例如 class X不能调用class的成员函数Y)?

提前致谢, 奥利弗

代码

void invoke(T argument) {
    fPtr(argument); // <-- VC++ error C2064: Expression does not evaluate to a function call, ok for gcc  (Q1)
}

格式错误。你需要一个对象来调用成员函数,而你这里没有。您在 MSVC 中看到错误但在 GCC 中看不到错误的原因可能是由于处理模板实例化的差异。需要完整的代码来给出确切的原因,但这可能是一个没有实际意义的练习——不管表面如何,代码在任何编译器上都是错误的,应该被修复。

第二个密码

Action<double, C> dblAction = Action<double, C>("x", &C::dummyDbl);

看起来像是 gcc5 中的错误,它在 gcc6 中编译正确。从 3.4.1

开始,它也可以在 CLang 中正确编译

这段代码到处编译:

A<double, C> dblAction{"x", &C::dummyDbl};

抱歉,问题 3 不清楚,SO 的最佳格式是每个 post 一个 个问题。所以我建议将问题 3 拆分成单独的 post.