Nir*_*man 5 c++ template-meta-programming constexpr c++11
我最近在这里问了一个问题(用SFINAE检测实例方法constexpr),我试图在编译时进行一些constexpr检测.最后,我发现可以利用noexcept这个来做:任何常量表达式也是如此noexcept.所以我把以下机器放在一起:
template <class T>
constexpr int maybe_noexcept(T && t) { return 0; }
...
constexpr bool b = noexcept(maybe_noexcept(int{}));
Run Code Online (Sandbox Code Playgroud)
这是正常的,b正如您所期望的那样,因为零初始化int是一个常量表达式.它应该正确地产生零(如果我改为int其他适当的类型).
接下来,我想检查某些东西是否可constexpr移动构造.所以我这样做了:
constexpr bool b = noexcept(maybe_noexcept(int(int{})));
Run Code Online (Sandbox Code Playgroud)
而且,这适用于int或用户定义的类型.但是,这会检查该类型是否包含constexpr默认构造函数和constexpr移动构造函数.所以,为了解决这个问题,我尝试改为declval:
constexpr bool b = noexcept(maybe_noexcept(int(declval<int>())));
Run Code Online (Sandbox Code Playgroud)
这导致在bgcc 5.3.0 中为false(不能使用任何一个clang,因为clang不能正确地生成常量表达式noexcept).没问题,我说,一定是因为declval(有趣的是)没有标记constexpr.所以我写了自己的天真版本:
template <class T>
constexpr T&& constexpr_declval() noexcept;
Run Code Online (Sandbox Code Playgroud)
是的,与标准库的工作方式相比,这是天真的,因为它会阻塞虚空和可能的其他东西,但它现在很好.所以我再试一次:
constexpr bool b = noexcept(maybe_noexcept(int(constexpr_declval<int>())));
Run Code Online (Sandbox Code Playgroud)
这仍然不起作用,b总是假的.为什么这不被视为常数表达式?这是一个编译器错误,还是我不了解基本原理constexpr?似乎在constexpr和未评估的上下文之间存在一些奇怪的交互.
constexpr表达式必须定义.你没有定义,所以在这种情况下int(constexpr_declval<int>())不是constexpr.
这意味着maybe_noexcept(int(constexpr_declval<int>()))不是constexpr,所以不是noexcept.
并且编译器正确返回false.
您也无法在a中调用UB constexpr.
我想不出一种方法来constexpr引用任意数据.我认为constexpr对齐存储的缓冲区被重新解释为对数据类型的引用,但在许多情况下都是UB,因此不是constexpr.
一般来说,这是不可能的.想象一下,你有一个类,其状态决定方法调用是否constexpr:
struct bob {
int alice;
constexpr bob(int a=0):alice(a) {}
constexpr int get() const {
if (alice > 0) throw std::string("nope");
return alice;
}
};
Run Code Online (Sandbox Code Playgroud)
现在,是bob::get constexpr不是?如果你有一个constexpr bob非积极的构造alice,并且......如果不是,那就不是.
你不能说"假装这个值是,constexpr并告诉我,如果某些表达是constexpr".即使你可以,也不会解决这个问题一般,因为国家一的constexpr表达式是否参数可以改变constexpr或不!
更有趣的bob().get() 是constexpr,而bob(1).get()不是.因此,您的第一次尝试(默认构造类型)甚至给出了错误的答案:您可以测试,然后执行操作,操作将失败.
该对象实际上是该方法的参数,如果没有al参数的状态,则无法确定函数是否为constexpr.
确定表达式是否的方法constexpr是在constexpr上下文中运行它并查看它是否有效.