关于这个指向成员函数的指针类型模板参数,标准是怎么说的?是我的代码有误,还是 MSVS 16.6 有问题?

What does the standard say about this pointer-to-member-function type template parameter? Is my code wrong, or is MSVS 16.6 buggy?

下面是一些适用于 GCC、Clang 和 MSVS 的代码(至少,那些当前在 Compiler Explorer 上可用的版本):

template <typename T, auto T::* MemberPtr>
struct Foo
{
    Foo(const T& e) : _e(e) {}

    void operator()() const
    {
        (_e.*MemberPtr)();
    }

private:
    const T& _e;
};

struct Bar
{
    void baz() const {}

    auto bind()
    {
        using BindingType = Foo<Bar, &Bar::baz>;
        return BindingType(*this);
    }
};

int main()
{
    Bar i;
    i.bind();
}

从 v16.6.1 开始,但是,MSVS 拒绝它:

Severity  Code   Description                                                                      Line
Error     C2973  'Foo': invalid template argument 'int'                                           23
Error     E2886  cannot deduce 'auto' template parameter type "auto T::*" from "void (Bar::*)()"  21
Error     C2440  'specialization': cannot convert from 'overloaded-function' to 'auto Bar::* '    22
Error     C3535  cannot deduce type for 'auto Bar::* ' from 'int'                                 23
Error     C2440  'specialization': cannot convert from 'int' to 'int Bar::* '                     23

通过去掉 MemberPtrT::* 限定符,该版本中的代码可以是 "fixed";所以:

template <typename T, auto MemberPtr>

标准对此有何规定? VS v16.6.1 是否引入了新的回归,或者它现在正在诊断总是被巧妙破坏的代码?

parameter/argument 组合有效

[temp.param]

4 A non-type template-parameter shall have one of the following (optionally cv-qualified) types:

  • ...
  • a type that contains a placeholder type.

[temp.arg.nontype]

1 If the type of a template-parameter contains a placeholder type, the deduced parameter type is determined from the type of the template-argument by placeholder type deduction. If a deduced parameter type is not permitted for a template-parameter declaration ([temp.param]), the program is ill-formed.

现在,auto T::* 是一个包含占位符类型的类型。 placholder type deduction

形式的变量声明中工作得很好
auto Bar::* foo = &Bar::baz;

所以 VS v16.6.1 没有拒绝这种非类型模板参数的业务。