size of template parameter pack pointer

Viewed 147

Im a little stuck.

How would i go about getting the size of the struct inside the parameter pack loop

if i pass just the struct i get the correct size, but if i pass it by a pointer or a ref the size is always 8

struct foo_s {
    int i1;
    int i2;
    int i3;
};

template<typename ...Args>
void Call(Args&& ...args)
{
    std::size_t index = 0;
    auto process = [&] <typename Arg> (Arg && arg, std::size_t index) {
        std::size_t size = sizeof(Arg); // always 8
    };
    (process(std::forward<Args>(args), index++), ...);
}


int main() {

    foo_s foo = { 1, 2, 3 };
    foo_s* pFoo = &foo;

    Call(pFoo);
}
2 Answers

We can remove the reference, then remove the pointer if it's a pointer type, and get the size of that:

std::size_t size = sizeof(std::remove_pointer_t<std::remove_reference_t<Arg>>);

If it's not a pointer type then remove_pointer_t will still give us T so there's no danger here.

This is of course deducing size by type, you could also do it by argument if you have it available, this lacks the flexibility of type sizeof though because it requires pointer-only types. It'd be done like :

std::size_t size = sizeof(*arg);

You can use a combination of std::remove_cvref to get the underlying type. If you care about pointer types too, add a layer of std::remove_pointer.

auto process = [&] <typename Arg> (Arg && arg, std::size_t index) {
    using UnderlyingType = typename std::remove_cvref<Arg>::type;         
    std::size_t size = sizeof(UnderlyingType); 
};

I firstly wrote that std::decay is also a possibility. While it behaves correctly for references, it does not have the resquested behaviours on arrays and pointer types.

Related