Get vtable class without object

I am trying to implement a system similar to the one described here . That is, (ab) using the vtable modification to change the behavior of an object at runtime. This is part of my attempts to create an efficient type-type wrapper in the C ++ project I'm working on.

In the example, if you can’t access it, copy the vtable with the memcpy()pointer thisas such:

void setType( const DataType& newType )
{
    memcpy( this, &newType, sizeof(DataType) );
}

However, I have a problem with this method: I do not have an object of the target class to copy vtable, and you do not want to create it, since some types are expensive to create.

Is there a way to access the vtable that will be placed in an object of this class without an object of this class?

It would be preferable if it were somewhat portable, but I pretty much came to terms with the fact that it was specific to the compiler; as such, the GCC / g ++ method would be acceptable if there is no other option. Suppose also that I am interested in building this on fairly standard OS and architectures.

I use C ++ 11 if that helps.

Edit: I want to be absolutely clear, I know how dangerous this behavior is. I am more interested in the idea and, perhaps, its narrow application in very controlled conditions than I am in it, it is a good idea for production software, despite what my introduction can offer.

+4
source share
1
struct many_vtable {
  void(*dtor)(void*);
  void(*print)(void const*,std::ostream&);
};
template<class T>struct tag_t{};
template<class T>constexpr tag_t<T> tag = {};

template<class T>
many_vtable const* make_many_vtable(tag_t<T>){
  static const many_vtable retval = {
    // dtor
    [](void* p){
      reinterpret_cast<T*>(p)->~T();
    },
    // print
    [](void const*p, std::ostream& os){
      os<<*reinterpret_cast<T const*>(p);
    }
  };
  return &retval;
}
struct many {
  many_vtable const* vtable=nullptr;
  std::aligned_storage_t<100, alignof(double)> buff;
  void clear(){if(vtable) vtable->dtor(&buff);vtable=nullptr;}
  ~many(){ clear(); }
  many()=default;
  many(many const&)=delete; // not yet supported
  many& operator=(many const&)=delete; // not yet supported

  explicit operator bool()const{return vtable!=nullptr;}

  template<class T,class...Args>
  void emplace(Args&&...args){
    static_assert(alignof(T) <= alignof(double), "not enough alignment");
    static_assert(sizeof(T) <= 100, "not enough size");
    clear();
    ::new((void*)&buff) T(std::forward<Args>(args)...);
    vtable=make_many_vtable(tag<T>);
  }
  friend std::ostream& operator<<(std::ostream& os, many const&m){
    if(!m.vtable) return os;
    m.vtable->print(&m.buff, os);
    return os;
  }
};

vtable. 100 , , , .

"" ( ) . , / .

, .

many m;
m.emplace<int>(3);
std::cout << m << '\n';
m.emplace<double>(3.14);
std::cout << m << '\n';

.

vtables, vtable .

+3

All Articles