StackPointer模板

时间:2013-03-07 23:25:51

标签: c++ templates metaprogramming template-meta-programming boost-mpl

我正在阅读“现代C ++设计”,并想出了一个构建一个类似指针的类的想法,但它会在堆栈而不是堆上分配对象。它可以用在通常会返回指向堆上分配的对象的指针的函数中。

在粘贴代码之前,我会问我的问题:

  1. 是否有类似的东西?
  2. 有机会被使用吗? (如果当然更准确地实施)
  3. 为什么使用boost::mpl::max_element(已注释掉)的版本不起作用?
  4. 如果没有参数,如何调用模板化构造函数? (我的意思是:template <class U> StackPointer() { ... })?
  5. 以下是代码:

    #include <iostream>
    
    #include <boost/mpl/vector.hpp>
    #include <boost/mpl/max_element.hpp>
    #include <boost/mpl/empty.hpp>
    #include <boost/mpl/pop_front.hpp>
    #include <boost/mpl/size.hpp>
    #include <boost/mpl/front.hpp>
    
    template <class V, size_t VS=boost::mpl::size<V>::type::value>
    struct max_size
    {
        typedef typename boost::mpl::pop_front<V>::type subvector;
        typedef typename boost::mpl::front<V>::type front_type;
        static size_t const value = sizeof(front_type) > max_size<subvector>::value ?
                    sizeof(front_type) : max_size<subvector>::value;
    };
    
    template <class V>
    struct max_size<V, 0>
    {
        static size_t const value = 0;
    };
    
    class StackPointerImplBase
    {
    public:
        virtual void clone(char const* from, char* to) const = 0;
    };
    
    template <class T>
    class StackPointerImpl : public StackPointerImplBase
    {
    public:
        virtual void clone(char const* from, char *to) const
        {
            new(to) T(*reinterpret_cast<T const*>(from));
        }
    };
    
    template <class Base, class DerivedTypes>
    class StackPointer
    {
    public:
        template <class T>
        StackPointer(T const& t)
        {
            std::cout << "Size of m_buf: "  << sizeof(m_buf) << std::endl;
            new(m_impl_buf) StackPointerImpl<T>();
            new(m_buf) T(t);
        }
    
        StackPointer(StackPointer const& sp)
        {
            //TODO: COPY m_impl_buf
            reinterpret_cast<StackPointerImplBase const*>(sp.m_impl_buf)->clone(sp.m_buf, m_buf);
        }
    
    public:
        ~StackPointer()
        {
            get_pointer()->~Base();
        }
    
        Base* operator->()
        {
            return get_pointer();
        }
    
    private:
        Base* get_pointer()
        {
            return reinterpret_cast<Base*>(m_buf);
        }
    
    private:
        //typedef max_size<DerivedTypes> xxx_type;
        //typedef typename boost::mpl::max_element<DerivedTypes>::type::type biggest_type;
        //char m_buf[sizeof(typename boost::mpl::max_element<DerivedTypes>::type::type)];
        char m_buf[max_size<DerivedTypes>::value];
        char m_impl_buf[sizeof(StackPointerImplBase)];
    };
    
    class Shape
    {
    public:
        virtual ~Shape() {}
    
        virtual void say() const { std::cout << "I'm a shape" << std::endl; }
    };
    
    class Circle : public Shape
    {
    public:
        virtual void say() const { std::cout << "I'm a circle" << std::endl; }
    
    private:
        float m_x;
        float m_y;
        float m_r;
    };
    
    class Line : public Shape
    {
    public:
        virtual void say() const { std::cout << "I'm a Line" << std::endl; }
    
    private:
        float m_x1;
        float m_y1;
        float m_x2;
        float m_y2;
    };
    
    
    typedef StackPointer<Shape, boost::mpl::vector<Circle, Line> > ShapeStackPtr;
    
    ShapeStackPtr read_shape()
    {
        Line c;
        return ShapeStackPtr(c);
    }
    
    
    int main(int argc, char *argv[])
    {
    
        {
            ShapeStackPtr shape = read_shape();
            shape->say();
        }
    
        return 0;
    }
    

2 个答案:

答案 0 :(得分:0)

Boost optional与您描述的非常相似。

它使用指针语法,因此它可以模拟指针说话中的NULL指针。

答案 1 :(得分:0)

您无法在堆栈上分配对象,然后返回指向它的任何内容。从函数返回后,堆栈帧消失,指向该内存无效。

当你在函数中声明局部变量时,它们会在堆栈上分配,然后在函数返回之前销毁,并且堆栈帧已经过时。

因此,您可以为堆上的对象分配内存,并通过指针引用它们。或者在堆栈中的函数中有局部变量。

或者你的意思是作为一种处理来自被调用函数的返回值的方法?但是,无论如何你需要将数据从堆复制到堆栈,所以如果你需要/想要堆栈上的副本,为什么不使用T obj = *foo()

对我来说,这听起来像是在试图让编译器已经有效处理的事情变得复杂。