代码之家  ›  专栏  ›  技术社区  ›  Jorge Bellon

std::tuple元素的延迟初始化

  •  0
  • Jorge Bellon  · 技术社区  · 7 年前

    std::aligned_storage

    然而,我不完全确定当我想要一份工作时我应该做什么 std::tuple 一步一步地 ,在不同的时间点以未指定的顺序初始化其成员。

    创建一个

    std::tuple< std::aligned_storage<sizeof(Types),alignof(Types)>::type...>
    

    然后将成员引用重新解释为 std::tuple<Types...>& ?

    例如:

    #include <bitset>
    #include <memory>
    #include <new>
    #include <tuple>
    #include <utility>
    
    template < class... Ts >
    class uninitialized_tuple {
        public:
            using tuple_type   = typename std::tuple<Ts...>;
            using buffer_type =
                std::tuple<
                    typename std::aligned_storage<sizeof(Ts),alignof(Ts)>::type...
                >;
    
            ~uninitialized_tuple() {
                destruct_helper<std::index_sequence_for<Ts...>>::erase(*this);
            }
    
            tuple_type& as_tuple() {
                reinterpret_cast<tuple_type&>(_storage);
            }
    
            bool valid() const {
                return _is_set.all();
            }
    
            template < size_t index, class... Args >
            void emplace( Args&&... args ) {
                using element_type = typename std::tuple_element<index,tuple_type>::type;
                new (&std::get<index>(_storage)) element_type( std::forward<Args>(args)...);
                _is_set.set(index);
            }
    
            template < size_t index >
            void erase() {
                using element_type = typename std::tuple_element<index,tuple_type>::type;
                if( _is_set[index] ) {
                    std::get<index>(_storage).~element_type();
                    _is_set.reset(index);
                }
            }
    
        private:
            template < class Seq >
            struct destruct_helper {
                static void erase( uninitialized_tuple& ) {}
            };
    
            template < size_t index, size_t... indices >
            struct destruct_helper<std::index_sequence<index,indices...>> {
                static void erase( uninitialized_tuple& value ) {
                    value.erase<index>();
                    destruct_helper<std::index_sequence<indices...>>::erase_one(value);
                }
            };
    
            buffer_type                _storage;
            std::bitset<sizeof...(Ts)> _is_set;
    };
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Vittorio Romeo    7 年前

    访问 as_tuple() 未定义的行为 https://en.cppreference.com/w/cpp/language/reinterpret_cast :

    每当试图通过AliasedType类型的glvalue读取或修改DynamicType类型的对象的存储值时,除非满足以下条件之一,否则该行为未定义:

    • AliasedType和DynamicType类似。

    • AliasedType是DynamicType的有符号或无符号变体(可能是cv限定的)。

    • AliasedType是std::byte(自C++17以来)字符或无符号字符:这允许检查任何对象作为字节数组的对象表示形式。

    推荐文章