C++ “constexpr是一个”吗;提示“;(如内联)或;具有约束力的请求”;到编译器?

C++ “constexpr是一个”吗;提示“;(如内联)或;具有约束力的请求”;到编译器?,c++,c++11,constexpr,C++,C++11,Constexpr,constexpr是编译器的一个指示符,还是它规定了一种行为 目前的例子如下: template<typename T> std::size_t constexpr getID() { return typeid(T).hash_code(); } 模板 std::size_t constexpr getID(){return typeid(t).hash_code();} hash\u code是一个运行时常量,但即使使用constexpr请求编译时求值,此代码段也会被删除。

constexpr
是编译器的一个指示符,还是它规定了一种行为

目前的例子如下:

template<typename T> 
std::size_t constexpr getID() { return typeid(T).hash_code(); }
模板
std::size_t constexpr getID(){return typeid(t).hash_code();}
hash\u code
是一个运行时常量,但即使使用
constexpr
请求编译时求值,此代码段也会被删除。只有在返回值用于预期编译时常量的地方,我们才会注意到这一点

那么
constexpr
是对编译器的“提示”(很像
inline
关键字)还是“绑定请求”?

来自:

如果使用以下参数调用constexpr函数或构造函数 如果不是常量表达式,则调用的行为就像函数是 不是constexpr,并且结果值不是常量表达式。 同样,如果constexpr的return语句中的表达式 函数的计算结果不是特定函数的常量表达式 调用时,结果不是一个常量表达式

因此,
constexpr
说明符表示在编译时对某些内容求值的可能性,并且在使用时会受到限制


对于您的特定代码片段,我认为C++11约束:

只有一条返回语句只包含文字值, constexpr变量和函数

未满足,因为哈希_代码定义为:

size_t hash_code() const;
在这种情况下,报告说:

对于constexpr函数,如果不存在函数参数值,则 函数调用替换将产生一个常量 表达式(5.19),程序格式不正确;无需诊断


我相信您的示例适合这里。

constexpr函数可用于计算编译时常量。因此,可以像这样使用它:

 constexpr int func(int a) { return a+2; }

 char x[func(10)];
如果在运行时调用func,则编译器可以在可能的情况下对该表达式求值。但这不是必须的,但如果输入也是常量,则通常会这样做

拥有constexpr构造函数也很重要。这是获得非POD类constexpr对象的唯一机会

    class Point
    {   
        private:    
            int x;
            int y;
        public:
            constexpr Point( int _x, int _y) : x(_x), y(_y) {}  
            constexpr int GetX() const { return x; }
    };  

    constexpr Point p{1,2};

    int main()
    {   

        char i[p.GetX()];
        return 0;
    }   

您的问题的完整答案有两个方面:

  • constexpr函数只能在所有 参数可以在编译时计算。它仍然可以用作 在运行时计算的正常函数

  • constexpr变量必须使用编译时计算的值进行初始化。 如果编译器无法执行此操作,则必须引发错误

  • 您可以将哈希代码分配给constexpr变量,然后获得编译器输出:

    #include <typeinfo>
    #include <array>
    
    template<typename T> 
    std::size_t constexpr getID() { 
    
        return []() {constexpr size_t id = typeid(T).hash_code(); return id;}(); }
    
    int main() {
        // both statement generate compiler errors
        //std::array<int, typeid(int).hash_code()> a;
        //constexpr size_t y = typeid(int).hash_code();
    
        size_t x = getID<int>();
    }
    
    #包括
    #包括
    模板
    std::size\u t constexpr getID(){
    return[](){constexpr size_t id=typeid(t).hash_code();return id;}();}
    int main(){
    //这两个语句都会生成编译器错误
    //std::数组a;
    //constexpr size_t y=typeid(int).hash_code();
    size_t x=getID();
    }
    
    constexpr
    是编译器的“提示”(如内联)还是“绑定请求”

    两者都不是。忘记评估它的时间。每当编译器认为有必要生成C++抽象机的行为时,就可以评估所有(有几个小例外,特别是涉及<>代码> Value)。当事情被评估时,没有太多的话要说

    编译器可以自由地生成代码,在运行时计算常量表达式,如果这不会产生不同的行为。如果有smarts,它可以在编译时自由地生成代码来评估未标记的内容

    如果不是关于编译时与运行时,那么
    constexpr
    是关于什么的呢

    constexpr
    允许将事物视为常量表达式。任何标记为
    constexpr
    的内容都必须能够以某种方式生成常量表达式

    对于函数,它们可以生成带有某些参数的常量表达式,但不能生成其他参数的常量表达式。但只要有一组参数可以生成常量表达式,函数就可以标记为
    constexpr
    。如果在函数调用中使用了这样一组参数,则该表达式是一个常量表达式。这是否意味着它是在编译时计算的?见上文。在编译器认为合适时对其进行评估。它的唯一含义是,您可以在需要常量表达式的上下文中使用它

    对于变量,它们要么是常量表达式,要么不是常量表达式。它们没有参数,因此如果
    constexpr
    它们总是必须用常量表达式初始化

    TL;DR
    constexpr
    是关于将事物标记为在常量表达式中可用,而不是决定何时对它们求值



    这样一来,您的函数模板似乎格式不正确。没有可能导致常量表达式的参数集。不过,该标准不需要对此进行诊断。

    注意,因为这是一个模板,所以在您使用一些
    t
    实例化它之前,没有任何函数。在这里,您可以看到此函数的实例化compiling@Mehrdad校正
    内联
    的thnx也不是提示。@rubenvb:“尽可能有效”没有意义(好,QOI)华夫饼,但是ODR规则改变(代码< >代码> >代码>的真正的GUT是强制的行为改变(至少在C++中,这是我在原来的注释中提到的)。所以基本上<代码> CONTXPRPR <代码>对语言是毫无意义的补充。@ Mehrdad:根本没有。您仍然可以使用编译时常量值调用constexpr函数,也可以在编译时对它们求值。@user2799037:问题不在于它们可以在编译时求值,而在于它们只能用于