为什么这个代码片段适用于C++17而编译器在使用C++11时会抱怨?

为什么这个代码片段适用于 C++17 而编译器在使用 C++11 时会抱怨(即https://godbolt.org/z/71G91P)?此代码片段是否存在任何潜在问题?

#include<iostream>

class ctx
{
    public:
        int map_create(void*){std::cout << "haha" << std::endl; return 0;};
};

ctx obj;
typedef int (ctx::*ctx_mem_func)(void*);

template <ctx_mem_func func>
int regHelper(void*) 
{
    ((&obj)->*func)(nullptr);
    return 0;
}

constexpr ctx_mem_func testFunc = &ctx::map_create;

typedef int(*callBackFunc)(void*);

int reg(callBackFunc)
{
    return 0;
}

int main()
{
    reg(regHelper<testFunc>);
    //But this expression is ok.
    reg(regHelper<&ctx::map_create>);
    
    std::cout << "this is a test" << std::endl;
} 

以下是使用 c++11(gun 10.0.2) 时的错误信息:

<source>: In function 'int main()':
<source>:30:28: error: no matches converting function 'regHelper' to type 'callBackFunc {aka int (*)(void*)}'
     reg(regHelper<testFunc>);
                            ^
<source>:13:5: note: candidate is: template<int (ctx::* func)(void*)> int regHelper(void*)
 int regHelper(void*) 
     ^

回答

这是 C++14 和 C++17 之间的区别。简化:

int f();
template<int (&)()> struct S {};
constexpr auto& q = f;
using R = S<q>; // valid in C++17, invalid in C++14

更改是允许对所有非类型模板参数进行常量评估,这意味着现在允许constexpr命名函数(成员函数等)的变量作为 NTTP,而以前只允许函数的实际名称。


以上是为什么这个代码片段适用于C++17而编译器在使用C++11时会抱怨?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>