Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.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++ 静态断言在使用concontint const时失败。constinit、constinit const、constexpr、const、nonconst变量中的混淆_C++_Constexpr_C++20_Constinit - Fatal编程技术网

C++ 静态断言在使用concontint const时失败。constinit、constinit const、constexpr、const、nonconst变量中的混淆

C++ 静态断言在使用concontint const时失败。constinit、constinit const、constexpr、const、nonconst变量中的混淆,c++,constexpr,c++20,constinit,C++,Constexpr,C++20,Constinit,我有一个关于编译时函数的问题。我理解静态断言应该只与类型一起工作,这些类型可以在编译时进行计算。因此,它不适用于std::string(目前,gcc10中不支持constexpr std::string),但适用于std::array(当我在编译时知道大小时)。我从Jason Turner看C++每周,所以这个片段来自这一集。 代码如下: #包括) 映射初始化为continitvaribale。现在,Continit保证表达式是零初始化的或常量初始化的。我用常量初始化,所以根据这个变量在编译时应

我有一个关于编译时函数的问题。我理解静态断言应该只与类型一起工作,这些类型可以在编译时进行计算。因此,它不适用于std::string(目前,gcc10中不支持constexpr std::string),但适用于std::array(当我在编译时知道大小时)。我从Jason Turner看C++每周,所以这个片段来自这一集。

代码如下:

#包括)
  • 映射初始化为continitvaribale。现在,Continit保证表达式是零初始化的或常量初始化的。我用常量初始化,所以根据这个变量在编译时应该是已知的(将静态变量的初始值设置为编译时常量),但它并不意味着常量,所以我们有编译时非常量变量,这个静态断言不能工作
  • Map被初始化为consnit const变量。现在我们有了编译时常量变量,但静态断言拒绝工作。静态断言需要bool()类型的上下文转换常量表达式,它是T类型的转换常量表达式,是隐式转换为T类型的表达式,其中转换的表达式是常量表达式为什么这不起作用?
  • 根据cppInsights,编译器生成的代码与constint const和constexpr相同

    Map被初始化为
    constint const
    变量。现在我们有了编译时常量变量,但是
    static\u assert
    拒绝工作

    第二种主张与第一种主张不同。我们没有编译时常量变量,因此
    static\u assert
    不起作用

    constinit
    不会使您的变量成为
    constepr
    变量,它只保证您具有恒定的初始化(因此命名为
    constinit
    )。事实上,
    constant
    甚至并不意味着
    const

    continit std::mutex m;
    
    是对
    constinit
    的有效且激励性的使用,并且仍然允许我锁定和解锁
    m

    拥有
    constexpr
    变量的唯一方法是声明您的变量
    constexpr
    (为声明的
    const
    整数类型保留了一个不幸的遗留部分,这里不适用)。如果您想拥有
    constexpr
    映射,则需要声明映射
    constexpr

    映射已初始化为constint const变量。。。但是静态断言拒绝工作。。。为什么这不起作用

    正如您所观察到的,
    static\u assert
    需要在编译时知道表达式

    但是,
    const
    只意味着逻辑常量,并不意味着该值在编译时已知(忽略使用常量表达式初始化的常量整数值的情况)

    类似地,
    continit
    仅表示静态初始化;同样,这并不意味着该值在编译时已知

    从你问题的措辞来看,我猜你是在期待:

    const
    +
    constint
    -->
    constepr


    但事实并非如此。如果您希望映射在编译时可用(即在
    静态断言
    中),则需要将其设置为
    constexpr
    )。

    您试图从错误的角度解决问题。您会看到一个声明为
    constint const
    的变量。您认为,由于对象是不可修改的,并且由常量表达式初始化,这意味着对象是常量表达式

    不是

    编译器是否知道其值?绝对地但“常量表达式”并不是这样定义的

    有些东西是一个恒定的表达式,因为标准说它是。声明的变量
    continit
    不是常量表达式,因为规则没有说明它是常量表达式。声明的变量
    const
    不是常量表达式,因为规则没有说明它是常量表达式(整数的某些情况除外,它早于
    constepr
    )。对于这两种标记的使用没有特别的规定

    如果变量声明为
    constexpr
    (或其中一个
    const
    整数异常),则该变量为常量表达式。并且只有常量表达式才能出现在
    static\u assert

    这是规定

    而且没有理由使用
    constint const
    这种特殊情况,因为如果您想要一个常量表达式。。。您可以编写
    constexpr
    。毕竟,您可能在某个模板代码中,有人给了您一个恰好是
    const
    T
    ,然后您在某处创建了一个
    constint
    变量。你没有要求它是一个恒定的表达;您只需要一个静态初始化的变量。恰好是
    const
    的类型只是偶然


    当然,编译器可以利用这些知识自由地进行各种特殊的优化。但这与编译器被允许做什么无关;这是关于语言的意思。如果你想从这个声明中得到特别的意义,你应该说得对。

    我觉得“混乱”有点强烈。“混乱”怎么样?这仍然保留了头韵,如果你喜欢这类东西:)离题,但是仅仅使用std::mutex m(在全局范围内,假设在构造其他静态时不使用它)有问题吗?@nosenseal没有。
    constinit
    唯一做的事情是强制执行的初始化是常量初始化。它不会改变初始化是否为常量初始化<代码>标准::互斥m已经做了c
    #include <array>
    #include <algorithm>
    
    template<typename Key, typename Value, std::size_t Size>
    struct Map final
    {
        std::array<std::pair<Key, Value>, Size> _data;
    
        [[nodiscard]] constexpr Value getMappedKey(const Key& aKey) const
        {
            const auto mapIterator = std::ranges::find_if(_data, [&aKey](const auto& pair){ return pair.first == aKey;});
    
            if(mapIterator != _data.end())
            {
                return mapIterator->second;
            }
            else
            {
                throw std::out_of_range("Key is not in the map");
            }
        }
    };
    
    enum class OurEnum
    {
        OUR_VALUE,
        OUR_VALUE2,
        OUR_VALUE3
    };
    
    enum class TheirEnum
    {
        THEIR_VALUE,
        THEIR_VALUE2,
        THEIR_VALUE3
    };
    
    
    // This Fails non constant variable of course
    /*
        Map<OurEnum, TheirEnum, 2> enumsConverter =
        {
            {
                {{OurEnum::OUR_VALUE, TheirEnum::THEIR_VALUE},
                {OurEnum::OUR_VALUE2, TheirEnum::THEIR_VALUE2}}
            }
        };
    */
    
    // This fails, it is const, but this does not guarentee that it will be created in compile time
    /*
        const Map<OurEnum, TheirEnum, 2> enumsConverter =
        {
            {
                {{OurEnum::OUR_VALUE, TheirEnum::THEIR_VALUE},
                {OurEnum::OUR_VALUE2, TheirEnum::THEIR_VALUE2}}
            }
        };
    */
    
    // This works
    /*
        constexpr Map<OurEnum, TheirEnum, 2> enumsConverter =
        {
            {
                {{OurEnum::OUR_VALUE, TheirEnum::THEIR_VALUE},
                {OurEnum::OUR_VALUE2, TheirEnum::THEIR_VALUE2}}
            }
        };
    */
    
    //How come this does not work? Oh i see, missing const because constinit does not apply constness
    /*
        constinit Map<OurEnum, TheirEnum, 2> enumsConverter =
        {
            {
                {{OurEnum::OUR_VALUE, TheirEnum::THEIR_VALUE},
                {OurEnum::OUR_VALUE2, TheirEnum::THEIR_VALUE2}}
            }
        };
    */
    
    // Okay, I added const specifier but still this makes static_assert fail because of non-constant condition
    // Why?
    
        constinit const Map<OurEnum, TheirEnum, 2> enumsConverter =
        {
            {
                {{OurEnum::OUR_VALUE, TheirEnum::THEIR_VALUE},
                {OurEnum::OUR_VALUE2, TheirEnum::THEIR_VALUE2}}
            }
        };
    
    
    int main() 
    {
        static_assert(enumsConverter.getMappedKey(OurEnum::OUR_VALUE) == TheirEnum::THEIR_VALUE);
    }