static constexpr指针到函数,编译器之间的差异 [英] static constexpr pointer-to-function, difference between compilers

查看:181
本文介绍了static constexpr指针到函数,编译器之间的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在回答此问题时,我尝试了以下代码与gcc(编译代码)和clang( code rejected ):

When answering this question, I tried the following code with gcc (code compiled) and clang (code rejected):

typedef long (*func)(int);

long function(int) { return 42; }

struct Test
{
    static constexpr func f = &function;
};

template<func c>
struct Call
{
    static void f()
    {
        c(0);
    }
};

int main()
{
    Call<Test::f>::f();
}



我不知道哪个编译器是正确的,虽然我认为constexpr初始化 Test :: f 是确定。错误clang输出是:

I am not sure which compiler is right, although I think the constexpr initialization of Test::f is ok. The error clang outputs is:

error: non-type template argument for template parameter of pointer type 'func'
       (aka 'long (*)(int)') must have its address taken




  1. 哪个编译器是正确的?

  2. 如果clang是正确的,为什么,这个错误是什么意思?

EDIT :为什么,请参阅 DyP的问题

推荐答案


14.3.2模板非类型参数[temp.arg.nontype]

14.3.2 Template non-type arguments [temp.arg.nontype]

非类型非模板模板参数的模板参数应为以下之一:

A template-argument for a non-type, non-template template-parameter shall be one of:

[...]

- 常量表达式(5.19),指定静态存储>持续时间的对象的地址,内部链接或具有外部或内部链接的函数,包括函数模板和函数模板ID,但不包括非静态类成员,表示(忽略括号) id-expression ,除了&如果名称引用函数或数组,则可以省略,并且如果相应的模板参数是引用则将被省略; [...]

— a constant expression (5.19) that designates the address of an object with static storage > duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; [...]

(n3485,强调我的)

(n3485, emphasis mine)

不知道为什么它是有限的,但我认为它可能与事实,函数地址在编译时不可用的事实(可能有替代模板实例化的目的)。

I don't know exactly why it's been limited, but I think it might be related to the fact that the function address is not available at compile time (there might be a substitute for template instantiation purposes).

编辑:由于Synxis的后续问题(评论)增强了回答

Enhanced answer due to a follow-up question (comment) of Synxis

constexpr func = &function;

^这是格式正确的;你可以使用函数的地址来初始化一个 constexpr 对象。
问题是,它明确禁止使用指针作为& identifier 之外的非类型模板参数:

^ this is well-formed; you can use the address of a function to initialize a constexpr object. The problem is that it's explicitly forbidden to use pointers as non-type template arguments other than of the form &identifier:

using My_Call     = Call < &function >;  // fine

constexpr func mypointer = &function;    // fine
using My_Ind_Call = Call < func >;       // forbidden, argument not of form `&id`

这篇关于static constexpr指针到函数,编译器之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆