可以添加“ constexpr”来改变行为吗? [英] Can adding 'constexpr' change the behaviour?

查看:69
本文介绍了可以添加“ constexpr”来改变行为吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出两个程序,其中源代码的唯一区别是是否存在一个 constexpr ,程序的含义是否有可能改变?

Given two programs where the only difference in the source code is the presence or absence of one constexpr, is it possible that the meaning of the program changes?

换句话说,如果有一个编译器选项要求编译器尽力尝试推断 constexpr

In other words, if there was a compiler option to ask the compiler to try really hard to infer constexpr where possible, would it break existing standard code and/or change its meaning in bad ways?

想象一下在一个代码库中原始开发人员忘记包含 constexpr 在可能的地方,也许是在C ++ 11之前编写的代码。如果编译器能够推断 constexpr 来帮助您继续工作,那就太好了。当然,也许它也应该在每次进行此推断时发出警告,鼓励您稍后显式添加 constexpr 。但这仍然有用。

Imagine dealing with a codebase where the original developer forgot to include constexpr in places where it was possible, perhaps code written before C++11. It would be great if the compiler would infer constexpr to help you get on with your work. Of course, perhaps it should also warn about each time it does this inference, encouraging you to explicitly add the constexpr later. But it would still be useful. My worry is that it might break things?

到目前为止,我唯一能想到的就是 constexpr 函数是 inline 的隐式函数,在某些情况下,添加 inline 可能会以不利的方式改变事物;例如,如果您打破了一个定义规则。

So far, the only thing I can think of is that constexpr functions are implicitly inline and there can be situations where adding inline can change things in bad ways; for example if you break the one-definition-rule.

推荐答案

有一个简单的技巧:

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 的不同重载。

if int foo(int) is constexpr, a different overload of bar is chosen by default.

运行不同的代码,任何行为都会发生。

With different code running, any behaviour change can occur.

实时示例(只需注释掉 #define X 的更改)。

live example (simply change which #define X is commented out).

示例设计:

char 重载可防止上述情况代码格式正确,无需诊断,因为所有模板都必须具有有效的专业名称。 foo< char> 可以提供。实际上,它的存在不是必需的:ADL可以从很远的地方找到 foo ,在 some_type * 上重载,然后将 some_type * 作为 T 传递。这意味着没有编译单元可以证明代码格式错误。

The char overload prevents the above code from being ill-formed, no diagnostic required, as all templates must have a valid specialization. foo<char> supplies that. In practice, its existence is not required: ADL could find a foo from far away, overloaded on a some_type*, then pass some_type* as T. Which means no compilation unit could prove the code was ill-formed.

Ts ... 使得 bar 重载优先级较低。因此,如果第一个匹配,就不会有歧义。仅当第一个不匹配时(由于由 foo(x)不是 constexpr 引起的SFINAE)才可以第二个重载被调用(或者,如果有人向它传递了参数)。

The Ts... makes that bar overload less-preferred. So if the first one matches, there is no ambiguity. Only if the first one fails to match (due to a SFINAE caused by foo(x) not being constexpr) does the second overload get called (or if, say, someone passed arguments to it).

这篇关于可以添加“ constexpr”来改变行为吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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