Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::less是否应该允许在编译时比较不相关的指针?_C++_Language Lawyer_Std_Compile Time - Fatal编程技术网

C++ std::less是否应该允许在编译时比较不相关的指针?

C++ std::less是否应该允许在编译时比较不相关的指针?,c++,language-lawyer,std,compile-time,C++,Language Lawyer,Std,Compile Time,考虑以下代码: #include <functional> #include <typeinfo> template <typename T> inline constexpr const void *foo = &typeid(T); int main() { constexpr bool a = std::less<const void*>{}(foo<int>, foo<float>); } 即

考虑以下代码:

#include <functional>
#include <typeinfo>

template <typename T>
inline constexpr const void *foo = &typeid(T);

int main()
{
    constexpr bool a = std::less<const void*>{}(foo<int>, foo<float>);
} 

即使我使用
std::less
,代码仍然无法编译。编译器错误与此相同
std::less
似乎被实现为
为了有效
constepr
函数,它应该具有结果为
constepr
的参数,而不是所有参数

比如说

constexpr int foo(bool b) { if (!b) throw 42; return 42; }
有效,
f(true)
可以在constexpr中使用(即使
f(false)
不能)

constexpr int a[2]{};
constexpr bool b=std::less{}(&a[0],&a[1]);
有效,足以允许
less::operator()
成为
constepr

我认为标准中没有规定constexpr的正确范围/值


所以所有的编译器都是正确的。

我不认为你所问的问题有一个明确的答案。这是一种特殊情况:标记库函数
constexpr
并不能解释调用该函数将生成常量表达式的情况


在这个问题解决之前,我认为您不能依赖于
std::less
能够在编译时比较不相关的指针,需要一个constexpr变量来满足以下规则:

对象声明中使用的constexpr说明符将对象声明为const。此类对象应具有文字类型,并应初始化。在任何constexpr变量声明中,初始化的完整表达式应为常量表达式。(注意强调的部分)

常量表达式必须是核心常量表达式,因此必须满足核心常量表达式规则:

一个关系运算符或相等运算符,其中结果未指定

在您的代码中,
&typeid(int)
&typeid(float)
未指定,原因是:

将不等指针与对象进行比较的定义如下:

  • 如果两个指针指向同一数组的不同元素或其子对象,则指向下标较高的元素的指针比较大
  • 如果两个指针递归地指向同一对象的不同非静态数据成员,或指向此类成员的子对象,则如果两个成员具有相同的访问控制且其类不是并集,则指向后一个声明成员的指针会比较大
  • 否则,两个指针的比较值都不大于另一个
&typeid(int)
&typeid(float)
符合第三个项目符号。及


如果两个操作数p和q比较相等,则p=q均为真,而pq均为假。否则,如果一个指针p比较大于一个指针q,p>=q,p>q,qOff主题:在比较之前将两个指针转换为uintptr\t对我来说并不是“神奇的”…@Aconcagua如果这样做,那么就无法找到它(在本节末尾)。如果不使用
a
,它可以简单地进行优化。如果你使用它会发生什么?例如,使用
返回a?99 : 101 ;
@TonyK即使没有使用变量,代码也不会编译,因此我怀疑如果我以某种方式使用它,代码是否会编译。这如何适用于这个特定问题?@_Static_assert:可能是吹毛求疵,但函数标记为
constexpr
(带有常量参数)通常不足以在常量表达式中使用。@HolyBlackCat修改了我的答案。是的,现在它似乎正确地解释了为什么
@HolyBlackCat就我所知,它不能,因为整个
typeid
是实现定义的,如果操作数是多态类类型,它将是一个运行时值。
constexpr int a[2]{};
constexpr bool b = std::less<const void*>{}(&a[0], &a[1]);