Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine whether an object has heap allocated members?

Is there a way to determine whether an object has at least one of its members on the heap?

I am trying to be able to distinguish objects like std::string or std::vector or std::list (yeah mostly containers) from all other types (unfortunately even containers with a single element are within my "scope of interest")

I am trying to do something like the following:

struct foo
{
private:
    int * _ptr;

public:
    foo() : _ptr(new int) {};
    ~foo() { delete _ptr; };
};

struct bar
{
private:
    int val;
};

template <typename T>
void func(T val)
{
    if constexpr (std::is_class_v<T>)
    {
        std::cout << std::setw(20) << typeid(T).name() << " is a class type." << std::endl;
        if (/* determine if foo has any heap allocations */)
        {
            // Do something #1.
            std::cout << std::setw(20) << typeid(T).name() << " does allocate on heap." << std::endl;
        }
        else
        {
            // Do something #2.
            std::cout << std::setw(20) << typeid(T).name() << " does NOT allocate on heap." << std::endl;
        }
    }
    else
    {
        // Do something #3.
        std::cout << std::setw(20) << typeid(T).name() << " is NOT a class type." << std::endl;
    }
}

int main()
{
    func(foo()); // foo does allocate on heap
    cout << endl;

    func(bar()); // bar does NOT allocate on heap
    cout << endl;
};

classes foo and bar are just examples, and the function func() has to perform functionality a bit different than couting to console.

like image 215
PatrykB Avatar asked Dec 11 '22 02:12

PatrykB


2 Answers

This is XY problem... I am trying to write a hash function that will be aware whether the user-defined key type stores any data on an array (just like std::string` would). I am fairly able to create a generic hash function that takes any type, but if that type has an array (a pointer) to some of it's stored data, problems become very tricky (pointers to dynamic arrays change at runtime, the same key at, different times will produce different hash value)

Be aware that some structure/class types have internal uninitialized padding, which may make your hash function work incorrectly.

Otherwise, std::is_trivially_copyable would be a good start.

like image 140
Kit. Avatar answered Mar 16 '23 10:03

Kit.


As others pointed out in the comments, there is no way to distinguish whether the pointer pointing to dynamically allocated or not. On the other hand, C++ standard <type_traits> provides type traits like

  • std::is_pointer to check a type is pointer
  • std::is_array to check wether array type
  • std::is_bounded_array to check the type is array of known bound.

and so on. Have a look at to the links, whether it suits your actual problem.


That being said, why it can't be solved with a member function which tells the information what you need?

For example:

struct foo
{
public:
    bool isHeapAllocated() const noexcept { return true; }
};

struct bar
{
public:
    bool isHeapAllocated() const noexcept { return false; }
};

Then simply call the function:

template <typename T> void func(T val)
{
    if constexpr (std::is_class_v<T>)
    {
        if (val.isHeapAllocated()) { 
            // Do something #1.
        }
        else
        {
            // Do something #2.
        }
    }
    else
    {
        // Do something #3.
    }
}
like image 37
JeJo Avatar answered Mar 16 '23 11:03

JeJo