如果被调用,是否是函数指针 [英] Is a function pointer odr-used if it is called
问题描述
考虑以下代码
template <typename T, typename C>
void g(T, C) {}
template <typename T, typename C>
struct G
{
static constexpr void (*m) (T, C) = &g;
};
void foo()
{
auto l = [](int){return 42;};
G<int, decltype(l)>::m(420, l);
}
这在C ++ 17的任何地方都是合法的,G::m
是通过内联变量等在G
中定义的.
This is legal in C++17 everywhere, G::m
is defined within G
via inlined variables and all that.
在C ++ 14和C ++ 11中奇怪的是,gcc拒绝使用此声明,但未定义m
,而clang接受了. 实时
What's weird is in C++14 and C++11 gcc rejects this stating m
is used but never defined, while clang accepts it. Live
m
是否已使用?还是这是gcc错误?
Is m
odr-used? Or is this a gcc bug?
推荐答案
TLDR m
尚未使用,这确实是GCC错误.
TLDR m
isn't odr-used, this is indeed a GCC bug.
直觉上,变量需要存储在内存中的某个位置.唯一的例外是,变量的值可以由编译器优化,并且从未以其他方式使用过. Odr-usage形式化了这个想法:只有在使用odr时,变量才需要定义.
Intuitively, variables needs to be stored in memory somewhere. The only exception is when the value of the variable can be optimized out by the compiler and never used in another way. Odr-usage formalizes this idea: a variable requires a definition only if it is odr-used.
Odr用法由 [basic.def.odr]定义
变量
x
的名称显示为可能评估的表达式ex
,由ex
奇特使用-除非将左值到右值转换应用于x
会产生不调用任何内容的常量表达式非平凡函数,并且如果x
是对象,则ex
是表达式e
的潜在结果集中的元素,其中将左值到右值转换应用于e
,或者e
是一个废弃值表达式.
A variable
x
whose name appears as a potentially-evaluated expressionex
is odr-used byex
unless applying the lvalue-to-rvalue conversion tox
yields a constant expression that does not invoke any non-trivial functions and, ifx
is an object,ex
is an element of the set of potential results of an expressione
, where either the lvalue-to-rvalue conversion is applied toe
, ore
is a discarded-value expression.
换句话说,x
不会被使用
-
x
不会显示为可能评估的表达式(例如decltype(x)
). -
x
不是对象(例如引用),并且将左值到右值转换应用于x
会产生一个常量表达式. -
x
是一个对象,将左值到右值转换应用于x
会产生一个常数表达式.此外,还有一个耦合"表达式e
,它已应用了左值到右值转换,或者被丢弃.
x
doesn't appear as a potentially-evaluated expression (e.g.decltype(x)
).x
isn't an object (e.g. a reference) and applying the lvalue-to-rvalue conversion tox
yields a constant expression.x
is an object and applying the lvalue-to-rvalue conversion tox
yields a constant expression. Furthermore, there is a "coupled" expressione
that either has the lvalue-to-rvalue conversion applied to it or is discarded.
耦合"是指直觉上有一些与x
紧密相关的封闭表达式,只能以某些方式使用而无需将x
存储在内存中.此概念通过对潜在结果的定义来形式化 [basic.def.odr ]
The "coupling" refers to the intuition that there is some enclosing expression closely related to x
that can only be used in certain ways without needing x
be stored in memory. This notion is formalized by the definition of potential results [basic.def.odr]
表达式
e
的潜在结果集定义如下:
The set of potential results of an expression
e
is defined as follows:
-
如果
e
是id表达式,则该集合仅包含e.
If
e
is an id-expression, the set contains only e.
如果e
是具有数组操作数的下标操作,则该集合包含该操作数的可能结果.
If e
is a subscripting operation with an array operand, the set contains the potential results of that operand.
如果e
是类成员访问表达式,则该集合包含对象表达式的可能结果.
If e
is a class member access expression, the set contains the potential results of the object expression.
如果e
是其第二个操作数是常量表达式的成员指针表达式,则该集合包含对象表达式的可能结果.
If e
is a pointer-to-member expression whose second operand is a constant expression, the set contains the potential results of the object expression.
如果e
的格式为(e1)
,则该集合包含e1
的可能结果.
If e
has the form (e1)
, the set contains the potential results of e1
.
如果e
是glvalue条件表达式,则该集合是第二和第三操作数的潜在结果集合的并集.
If e
is a glvalue conditional expression, the set is the union of the sets of potential results of the second and third operands.
如果e
是逗号表达式,则该集合包含右操作数的可能结果.
If e
is a comma expression, the set contains the potential results of the right operand.
否则,该集合为空.
在e
可能结果之内的表达式ex
与e
耦合".
An expression ex
that is within the potential results of e
is "coupled" with e
.
应用定义
-
m
可能被评估. - 将左值到右值转换应用于
m
会产生一个常量表达式. -
m
是一个对象. -
m
是一个表达式,其潜在结果包括m
,并且已应用了从左值到右值的转换.
m
is potentially evaluated.- Applying the lvalue-to-rvalue conversion to
m
yields a constant expression. m
is an object.m
is an expression whose potential results includesm
and has the lvalue-to-rvalue conversion applied to.
因此,我们得出结论m
没有被滥用.
We thus conclude m
isn't odr-used.
这篇关于如果被调用,是否是函数指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!