Assemble network packet on stack for iovec
The iterator is not behaving correctly
There are various reasons std::copy() doesn't work on stack_stack, and it all has to do with the iterator. First, you are missing difference_type. Since your iterators do not support taking the difference, set it to void:
using difference_type = void;

Second, your comparison operators are wrong. They should take a const reference to other, and you can access member variables of other directly, so:
bool operator==(const iterator &amp;other) const {
   return ptr == other.ptr;
}

Also, while this is a trivial comparison operator, it is good to define operator!= in terms of operator==, to avoid potential mistakes:
bool operator!=(const iterator &amp;other) const {
    return !(*this == other); // Just invert the result of operator==
}

Last, the result of operator* should be a reference to the actual data, not a pointer, so:
reference operator*() {
    return *static_cast&lt;pointer&gt;(ptr);
}

Now it sort of works, and std::copy() is happy. In your own code, you need to change some use of -&gt; to . to make it print the contents of a stack, like so:
for (auto item: stack) {
    std::cout &lt;&lt; item.data &lt;&lt; &quot;\n&quot;;
}

Avoiding void* hacks
Well, you have created a problem for yourself. Each element of the stack points to the next element, but it has a different type. The cleanest solution I see without changing the type system used for stack_stack is to do this:
struct iterator {
    ...
    using pointer = const stack_stack*;
    ...
    iterator&amp; operator++() {
        ptr = reinterpret_cast&lt;pointer&gt;(ptr-&gt;next);
        return *this;
    }
    ...
    reference operator*() {
        return ptr-&gt;value;
    }

    pointer ptr;
};

So we removed all of the lies, except the one about the type when following ptr-&gt;next.
The cleanest approach
If you want to do it even cleaner, then you should not have a template parameter length. Maybe also don't call it a stack, it more accurately resembles one element of a singly-linked list. To keep track of the length of this list, I would create a separate type that resembles the list as a whole, and which stores the length and a pointer to the head, both of which we will update when we add elements:
template&lt;class T&gt;
struct stack_list {
    struct item {
        const T value;
        const item *const next;

        // Constructor which will update the head of stack_list
        item(const T &amp;value, const item *&amp;head): value(value), next(head) {
            head = this;
        }

        // Delete copy constructor, move and assignment operators
        item(const item &amp;other) = delete;
        item &amp;operator=(const item &amp;other) = delete;
        item &amp;operator=(const item &amp;&amp;other) = delete;
    };

    struct iterator {
        ... // left as an excercise to the reader
    };

    size_t size{};
    const item *head{};

    [[nodiscard]] item push_front(T value) {
        size++;
        return {value, head}
    }
}

Then you can use it like so:
auto my_data = ...;

stack_list&lt;ioitem&gt; sl;
auto my_buffer = sl.push_front({my_data.begin(), my_data.size()});

std::cout &lt;&lt; &quot;List size: &quot; &lt;&lt; sl.size &lt;&lt; &quot;\n&quot;
          &lt;&lt; &quot;First element: &quot; &lt;&lt; sl.head-&gt;value &lt;&lt; &quot;\n&quot;;

Using your class for building iovecs
As you noticed you still need to convert your stack (or list) of ioitems to an array of struct iovec. So it might be better to build this array directly. If you want to do it on the stack, then the safest option is to just go with a std::array&lt;iovec, N&gt;, where N is large enough to handle most or all cases. If the required size can vary a lot, then you can perhaps make a class that holds a union of a std::array and a std::vector, and switches to the vector if the array is full. You might be able to use an existing library implementing small vector optimization, but since you basically always push_front(), your own implementation that starts at the back of the array might be the most efficient. It might look like:
template&lt;size_t N = 8&gt;
class iovec_builder {
    std::array&lt;struct iovec, N&gt; iov;
    size_t iovlen{};

public:
    void push_front(struct iovec item) {
        if (iovlen == N) {
            // handle array being full
        } else {
            // add starting from the back
            iovlen++;
            iov[N - iovlen] = item;
        }
    }

    struct iovec *get_iov() {
        return &amp;iov[N - iovlen];
    }

    size_t get_iovlen() const {
        return iovlen;
    }
};

And use it like:
iovec_builder iovb;
std::string my_data(&quot;Hello World&quot;);
iovb.push_front({my_data.data(), my_data.len()});
iovb.push_front({..., ...});

struct msghdr msg{};
msg.iov = iovb.get_iov();
msg.iovlen = iovb.get_iovlen();
...
sendmsg(fd, &amp;msg, ...);

It might waste a bit of stack space, but you'll waste more by having a linked list and having to copy it into an array.