【问题标题】:Template parametric type Allocator in C++C++ 中的模板参数类型分配器
【发布时间】:2021-03-31 16:08:29
【问题描述】:

我有以下有效的玩具代码:

#include <cstdlib>
#include <vector>

template <typename T>
struct Dummy {
        using value_type = T;
        using size_type = size_t;
        using difference_type = ptrdiff_t;
        using pointer = value_type*;
        using const_pointer = const value_type*;
        using reference = value_type&;
        using const_reference = const value_type&;

        Dummy() = default;
        Dummy(const Dummy&) = default;
        
        pointer allocate(size_type n, const void* hint = 0) {
                (void)hint;
                return static_cast<pointer>(aligned_alloc(128, n * sizeof(T)));
        }

        void deallocate(void* p, size_type) {
                if (p)
                        free(p);
        }
};

int main()
{
        
        std::vector<int, Dummy<int, 16>> v;
        
        
        for (size_t i = 1; i < 5000; ++i)
                v.push_back(i);
        
        
        return 0;
}

现在我想对对齐方式进行模板化(而不是放入构造函数中)。我尝试在模板中添加一个整数参数

template <typename T, size_t align>
struct Dummy {
        using value_type = T;
        using size_type = size_t;
        using difference_type = ptrdiff_t;
        using pointer = value_type*;
        using const_pointer = const value_type*;
        using reference = value_type&;
        using const_reference = const value_type&;

        Dummy() = default;
        Dummy(const Dummy&) = default;

        pointer allocate(size_type n, const void* hint = 0) {
                (void)hint;
                return static_cast<pointer>(aligned_alloc(align, n * sizeof(T)));
        }

        void deallocate(void* p, size_type) {
                if (p)
                        free(p);
        }
};

int main()
{
        
        std::vector<int, Dummy<int, 128>> v;
        
        
        for (size_t i = 1; i < 5000; ++i)
                v.push_back(i);
        
        
        return 0;
}

g++clang++ 都出现很多编译错误:例如

/usr/include/c++/10.2.0/bits/alloc_traits.h:78:11: error: no type named 'type' in 'struct std::__allocator_traits_base::__rebind<Dummy<int, 128>, int, void>'
   78 |     using __alloc_rebind
      |           ^~~~~~~~~~~~~~
In file included from /usr/include/c++/10.2.0/vector:67,
                 from aligned.cpp:4:
/usr/include/c++/10.2.0/bits/stl_vector.h: In instantiation of 'class std::vector<int, Dummy<int, 128> >':
aligned.cpp:62:43:   required from here
/usr/include/c++/10.2.0/bits/stl_vector.h:474:20: error: '_M_allocate' has not been declared in 'std::_Base<int, Dummy<int, 128> >'
  474 |       using _Base::_M_allocate;
      |                    ^~~~~~~~~~~
/usr/include/c++/10.2.0/bits/stl_vector.h:475:20: error: '_M_deallocate' has not been declared in 'std::_Base<int, Dummy<int, 128> >'
  475 |       using _Base::_M_deallocate;

我不明白发生了什么。我注意到即使我不在类中使用align,编译器也会以同样的方式抱怨。相反,如果我在模板中放置了一个未使用的typename,那么一切都可以正常编译。 你能帮帮我吗?

【问题讨论】:

  • 分配器不控制对齐(它会受到它的影响)。 C++17 引入了关键字来控制类的对齐。选择一个:stackoverflow.com/q/65826663/1387438
  • 感谢您提供的信息。分配器不控制对齐是什么意思?我的第一个示例(没有任何问题的示例)不正确吗?但是我有(唉!)维护一些遗留代码,我必须只使用 C++11,
  • 这是一个相当复杂的话题,请参阅youtu.be/IAdLwUXRUvg?t=1266 并选择我的问题(上面链接)。
  • 好的,据我所见,您的参考中有一些关于placement new 运算符的微妙之处。我知道一些事情,这就是为什么我试图使用cstdlib 来避免它。然而让我感到惊讶的是我的代码甚至没有编译,我真的无法解释错误信息。!

标签: c++ c++11 templates allocator


【解决方案1】:

我想我找到了解决问题的方法,尽管我不确定我是否完全理解了所有细节。

感谢:thisthis 我设法写了

template <typename T, size_t align>
struct Dummy {
        using value_type = T;
        using size_type = size_t;
        using difference_type = ptrdiff_t;
        using pointer = value_type*;
        using const_pointer = const value_type*;
        using reference = value_type&;
        using const_reference = const value_type&;

        template<class Other>
        struct rebind { using other =  Dummy<Other, align>; };



        
        Dummy() {};
        Dummy(const Dummy&) {};

        template <typename Other>
        Dummy(const Dummy<Other, align>&) {}
        
        pointer allocate(size_type n, const void* hint = 0) {
                (void)hint;
                return static_cast<pointer>(aligned_alloc(align, n * sizeof(T)));
        }

        void deallocate(void* p, size_type) {
                if (p)
                        free(p);
        }
};

它编译并且似乎具有正确的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多