在 C++20 中,我们有
constexpr T* std::allocator<T>::allocate( std::size_t n );
Run Code Online (Sandbox Code Playgroud)
在编译时分配类型化动态未初始化存储(并construct_at构造对象)。
但是我们在编译时是否有类型化的非动态存储,例如类型化的 aligned_storage?
编辑:一种有用的用法是实现 constexpr static_vector:
template<class T, size_t Cap>
class static_vector {
size_t size;
Storage<T, Cap> storage;
};
Run Code Online (Sandbox Code Playgroud)
是的,您可以使用std::array<std::optional<T>, Cap>,或者union如果您不希望数组中每个值都有自己的布尔值的开销,则可以使用 a 自己实现它。C++17 使我们能够在constexpr尚无活动成员时激活联合成员,而 C++20 允许我们在constexpr遵循正确的对象生存期规则的情况下更改活动成员。请注意,激活成员或更改哪个成员处于活动状态的方法很少union- 特别是,您不能使用指向成员的指针语法来激活联合成员。
这是该方法的示例union:https://gcc.godbolt.org/z/h6djsYshr
#include <cstddef>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
namespace example
{
struct None {};
template<class T, std::size_t Cap>
struct Storage
{
union U
{
None none;
T some;
constexpr U() noexcept : none{} {}
};
U values[Cap];
};
template<class T, std::size_t Cap>
class static_vector
{
std::size_t size{};
Storage<T, Cap> storage;
public:
constexpr ~static_vector() noexcept
{
for(std::size_t i = 0; i < size; ++i)
{
std::destroy_at(&storage.values[i].some);
}
}
template<typename... Args>
constexpr T& emplace_back(Args&&... args)
{
if(size >= Cap)
{
throw std::bad_alloc();
}
auto& u{storage.values[size]};
std::construct_at(&u.some, std::forward<Args>(args)...);
++size;
return u.some;
}
};
}
namespace example_usage
{
struct CounterHolder
{
int& counter;
constexpr CounterHolder(int& counter_) noexcept
: counter{counter_}
{
}
};
[[nodiscard]] constexpr int demo() noexcept
{
example::static_vector<CounterHolder, 10> v;
int counter{};
++v.emplace_back(counter).counter;
++v.emplace_back(counter).counter;
++v.emplace_back(counter).counter;
return counter;
}
static constexpr int const demoResult{demo()};
[[nodiscard]] int showDemoResultInAssembly() noexcept
{
return demoResult;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
158 次 |
| 最近记录: |