鉴于两个程序中源代码的唯一区别在于是否存在一个constexpr
,程序的含义是否可能发生变化?
换句话说,如果有一个编译器选项要求编译器尽可能地尝试推断constexpr
,那么它是否会破坏现有的标准代码和/或以错误的方式改变其含义?
想象一下处理代码库,原始开发人员忘记在可能的地方包含constexpr
,也许是在C ++ 11之前编写的代码。如果编译器会推断constexpr
来帮助您继续工作,那将会很棒。当然,或许它也应该在每次进行此推断时发出警告,鼓励您稍后明确添加constexpr
。但它仍然有用。我担心它可能会破坏它?
到目前为止,我唯一能想到的是constexpr
函数隐含inline
并且可能会出现添加inline
可能会以不良方式改变事物的情况;例如,如果你违反了单定义规则。
答案 0 :(得分:14)
有一个简单的伎俩:
template<int n>struct i{};
int foo(int){return 0;}
constexpr int foo(char){return 'a';}
template<class T=int, T x=1,i<foo(x)>* =nullptr>
bool bar(){return true;}
template<class T=int, T x=1,class...Ts>
bool bar(Ts...){return false;}
如果int foo(int)
是constexpr,则默认选择bar
的不同重载。
运行不同的代码时,可能会发生任何行为更改。
live example(只需更改注释掉的#define X
)。
示例设计:
char
重载可防止上述代码格式错误,无需诊断,因为所有模板都必须具有有效的特化。 foo<char>
提供了这一点。在实践中,不需要它的存在:ADL可以从远处找到foo
,在some_type*
上重载,然后将some_type*
作为T
传递。这意味着没有编译单元可以证明代码格式不正确。
Ts...
使bar
过载不那么首选。因此,如果第一个匹配,则没有歧义。只有当第一个不匹配时(由于foo(x)
导致的SFINAE不是constexpr
),才会调用第二个重载(或者,如果有人将参数传递给它)。
答案 1 :(得分:4)
鉴于两个程序中源代码的唯一区别是 是否存在一个constexpr,是否有意义 该计划的变化?
是的,至少对于constexpr功能来说是这样。这就是为什么不允许实现选择哪些标准函数被标记为constexpr的原因,主要问题是用户可能通过SFINAE观察到不同的行为。 LWG issue 2013: Do library implementers have the freedom to add constexpr?中记录了这一点(强调我的):
在向全体委员会提交表决时表达了一些担忧 到WP状态,这个问题已经解决没有足够的 想到了不同的库实现的后果, 因为用户可能会使用SFINAE来观察其他相同代码的不同行为。问题又回到了审核状态,将会是 在波特兰与一个更大的团体再次讨论。波特兰注意事项: John Spicer同意代表Core在任何此类问题上的担忧 LWG内部的讨论。