An expirable LRU cache implementation
I don't see why the typenames NodePtr and NodeIter are public.  Node itself is private, and none of the public interface uses these two types, so I think they should be private, too.

I'm not sure I like this interface:
V Get(K key);

This means we can only cache value types.  Not only that, but there's no way to indicate &quot;not in the cache&quot;; I see the implementation default-constructs a return value in that case - further limiting the types that can be used.

Expired() expects that the mutex is held, but is missing a comment stating that, so it took too long to confirm that it's used correctly.

What's going on here?

NodePtr node = std::make_shared&lt;Node&gt;(Node{key, value, timestamp});


Why construct a Node and pass it to make_shared() to copy?  It would be better to make_shared() directly:
NodePtr node = std::make_shared&lt;Node&gt;(key, value, timestamp);