How*_*owP 0 c++ constexpr c++20 constinit
我有一个关于编译时函数的问题。我知道 static_assert 应该只适用于可以在编译时评估/计算的类型。所以它不适用于 std::string (然而,gcc10 中不支持 constexpr std::string)但可以使用 std::array(当我在编译时知道大小时)。我正在观看 Jason Turner 的 C++ Weekly,所以这个片段来自这一集https://www.youtube.com/watch?v=INn3xa4pMfg。
代码在这里:https : //godbolt.org/z/e3WPTP
#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);
}
Run Code Online (Sandbox Code Playgroud)
我在玩这个示例并发现 static_assert 不适用于 constinit const 初始化映射。我注释掉了所有可能性,我想解释一下。
根据 cppInsights,编译器生成的代码与 constinit const 和 constexpr 相同。
Map 被初始化为
constinit const变量。现在我们有编译时常量变量但static_assert拒绝工作
第二个主张不是从第一个主张而来的。我们没有编译时常量变量,因此static_assert不起作用。
constinit不会使您的变量成为constexpr变量,它仅保证您具有常量初始化(因此名称为constinit)。事实上,constinit甚至不暗示const:
constinit std::mutex m;
Run Code Online (Sandbox Code Playgroud)
是一个有效且激励性的用途constinit,并且仍然允许我锁定和解锁m。
拥有constexpr变量的唯一方法是声明您的变量constexpr(不幸的是,对于声明的整型类型const,这并不适用)。如果你想要一张constexpr地图,你需要声明你的地图constexpr。