boost-ext / te

C++17 Run-time Polymorphism (Type Erasure) library
451 stars 38 forks source link

How to use a non const erased type ? #14

Closed uknys closed 6 years ago

uknys commented 6 years ago

Hello,

I wanted to know if it was possible to use [Boost].TE with types which have no const member functions, couldn't find a way to make it work to pass it by ref.

Here's the code :

#include <iostream>
#include <boost/te.hpp>

namespace te = boost::te;

// Define interface of something which is drawable
struct drawable {
  void draw(std::ostream &out)  {
    te::call([](auto &self, auto &out) { self.draw(out); }, *this, out);
  }
};

// this works 
void draw(te::poly<drawable> drawable) { drawable.draw(std::cout); }

// this doesn't work
// void draw(te::poly<drawable>& drawable) { drawable.draw(std::cout); }

// this doesn't work either
// void draw(te::poly<drawable&> drawable) { drawable.draw(std::cout); }

struct Square {
  int value {0};
  void draw(std::ostream &out) { out << "Square"; out << '\n'; value += 1; }
};

struct Circle {
  void draw(std::ostream &out) { out << "Circle";  out << '\n';}
};

int main() {
    auto x = Circle{};
    auto y = Square{};

    draw(x); // prints Circle
    draw(y); // prints Square

    // should return 1 if it was passed by ref, but as it's passed by value it's 0
    std::cout << y.value << '\n'; 

    return 0;
}

Here's the wandbox : https://wandbox.org/permlink/x3Mo2N4toRhCol2H

uknys commented 6 years ago

Well I got it working by creating a new storage type like dyno::non_owning_storage for Boost::TE.

struct viewer_storage {
  template <class T, class T_ = std::decay_t<T> >
  constexpr explicit viewer_storage(T &&t, te::detail::void_ptr &ptr) noexcept {
    ptr.reset(&t, 
        []([[maybe_unused]] void *ptr) {},
        [](void *ptr) -> void * { return static_cast<T_ *>(ptr); });
  }
};

Here's an example to see it working : https://wandbox.org/permlink/9rADpyr92if0Z7CI And in Compiler Explorer : https://godbolt.org/g/ERscKM

uknys commented 6 years ago

This issue is fixed with this commit #17