可以添加' constexpr'改变行为?

时间:2015-09-04 11:34:43

标签: c++ c++11 constexpr

鉴于两个程序中源代码的唯一区别在于是否存在一个constexpr,程序的含义是否可能发生变化?

换句话说,如果有一个编译器选项要求编译器尽可能地尝试推断constexpr,那么它是否会破坏现有的标准代码和/或以错误的方式改变其含义?

想象一下处理代码库,原始开发人员忘记在可能的地方包含constexpr,也许是在C ++ 11之前编写的代码。如果编译器会推断constexpr来帮助您继续工作,那将会很棒。当然,或许它也应该在每次进行此推断时发出警告,鼓励您稍后明确添加constexpr。但它仍然有用。我担心它可能会破坏它?

到目前为止,我唯一能想到的是constexpr函数隐含inline并且可能会出现添加inline可能会以不良方式改变事物的情况;例如,如果你违反了单定义规则。

2 个答案:

答案 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内部的讨论。