StackPointer template

StackPointer template

本文关键字:template StackPointer      更新时间:2023-10-16

我正在阅读"现代c++设计",并突然想到构建一个类,它将像指针一样工作,但它将在堆栈而不是堆上分配对象。它可用于通常返回指向堆上分配的对象的指针的函数。

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

    已经有类似的东西了吗?
  1. 有机会被使用吗?(当然,如果实现得更准确的话)
  2. 为什么版本使用boost::mpl::max_element(注释掉)不工作?
  3. 如何调用模板构造函数,如果它没有参数?(我的意思是:template <class U> StackPointer() { ... })?

代码如下:

#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;
}

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

它使用指针语法,所以它可以模拟指针语言中的NULL指针。

你不能在堆栈上分配一个对象,然后返回指向它的任何东西。当你从一个函数返回后,堆栈帧已经消失,指向那个内存是无效的。

当你在函数中声明局部变量时,它们在堆栈上分配,然后在函数返回之前销毁,堆栈帧作废。

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

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

对我来说,这听起来像是你试图使编译器已经有效处理的事情复杂化。