0

Try to implement a tiny-any:

#include <iostream> #include <type_traits> #include <memory> class TinyAny { public: template <typename Tp> TinyAny(Tp&& val) : data(std::make_shared<unsigned char[]>(sizeof(val))) { new(data.get()) Tp(std::forward<Tp>(val)); } template <typename Tp> TinyAny &operator =(Tp&& val) { data = std::make_shared<unsigned char[]>(sizeof(val)); new(data.get()) Tp(std::forward<Tp>(val)); return *this; } template <typename Tp> Tp get() { return *reinterpret_cast<Tp *>(data.get()); } private: std::shared_ptr<unsigned char[]> data; }; int main() { // var = "abc"; // std::cout << var.get<const char *>() << std::endl; } 

if uncomment var = "abc" will get the fellowing error:

<source>: In instantiation of 'TinyAny& TinyAny::operator=(Tp&&) [with Tp = const char (&)[4]]': <source>:40:11: required from here <source>:17:9: error: new cannot be applied to a reference type 17 | new(data.get()) Tp(std::forward<Tp>(val)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <source>:17:44: error: invalid conversion from 'const char*' to 'char' [-fpermissive] 17 | new(data.get()) Tp(std::forward<Tp>(val)); | ~~~~~~~~~~~~~~~~^~~~~ | | | const char* 

The type of val is const char*, but I cannot understand which one is char? Or, how can I fix this error?

Source Code: https://gcc.godbolt.org/z/zW7fPc6G3

8
  • 1
    You can refer to the implementation of libstdc++, it is not very complicated. Commented Jul 6, 2022 at 3:14
  • @康桓瑋 Thanks, I had read the source code of std::any. I just want to implement a 'tiny-any' by normal memory which can be not type-safed or not highly-efficient. In fact, what confused me is the aboved error message. Commented Jul 6, 2022 at 3:36
  • 1
    Um, that's not at all what std::any's interface is like. Copying the any will copy its contents, not merely reference a shared_ptr. And a "not type-safed" any is just a void* so... just use that. Commented Jul 6, 2022 at 3:37
  • 1
    How is this supposed to behave? It will free the memory, but will not call the stored type's destructor. Commented Jul 6, 2022 at 6:28
  • 1
    The immediate problem is that you need to decide whether var = "abc" is supposed to cause var to store a const char[4] array or whether it is supposed to store a char*. If the former, you need some special cases, since the new expression doesn't work like this with an array type. If the latter, then you should std::decay the type when storing or retrieving. Commented Jul 6, 2022 at 6:30

2 Answers 2

0

My finally implement:

#include <type_traits> #include <utility> class TinyAny { template<typename Tp> class AnyData { public: static void create(void **data, Tp && val) { *data = new Tp(std::forward<Tp>(val)); } static void deleter(void *data) { auto ptr = static_cast<Tp *>(data); delete ptr; } }; public: template <typename Tp__, typename Tp = std::decay_t<Tp__>> TinyAny(Tp__&& val) : deleter(AnyData<Tp>::deleter) { AnyData<Tp>::create(&data, std::forward<Tp>(val)); } ~TinyAny() { deleter(data); data = nullptr; } template <typename Tp> TinyAny &operator = (Tp&& val) { TinyAny temp{std::forward<Tp>(val)}; swap(std::move(temp)); return *this; } template <typename Tp> Tp get() { return *static_cast<Tp*>(data); } private: TinyAny &swap(TinyAny && another) noexcept { std::swap(data, another.data); std::swap(deleter, another.deleter); return *this; } private: void *data; void (* deleter)(void *data); }; 
Sign up to request clarification or add additional context in comments.

Comments

0

Your any class need to contain a pointer to std::type_info to ensure type safety. You can refer to my full implementation of std::any Here .

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.