Chain-of-Responsibility in C++11 using smart pointers
First nit: boss and supervisor strike me as basically synonymous. So it's kind of confusing that you're using both of them as identifiers in your program. Are these identifiers supposed to be meaningful, or are they just placeholders like Alice or Bob?



Also a nit: If your destructor doesn't do anything, don't write it.

virtual  ~Boss() override {}


is just a waste of characters. (The definition of ~Handler() is important because you have to hang the virtual specifier on it; but the definition of ~Boss() is perfectly redundant.)



//receivers may be released at run time.
boss.reset();


I think I don't get it. If this line had instead read supervisor.reset(), wouldn't boss have become unreachable, as far as handling requests was concerned? (Because requests go first to agent; then to agent-&gt;m_successor if it's non-null; but supervisor is gone, so handling just stops there.)

This seems like a bug in your design.



void handle(Event e) override {
    // ...
            ptr-&gt;handle(e);


This function call makes a copy of Event e, which might be expensive since Event contains an arbitrarily long std::string. You could fix this in either of two ways: either by changing the function signature to

void handle(const Event&amp; e)


(throughout the whole hierarchy, of course), or else by changing the function call to

            ptr-&gt;handle(std::move(e));  // move, don't copy




I know you said "performance isn't a concern", but any time you're using exception handling for control flow you should really reconsider your design. Instead of throwing and catching bad_weak_ptr, I'd recommend

    if (std::get&lt;0&gt;(e) == 1) {
        std::cout &lt;&lt; "Agent handled the request: " + std::get&lt;1&gt;(e) &lt;&lt; std::endl;
    } else if (auto ptr = m_successor.lock()) {
        ptr-&gt;handle(e);
    } else {
        std::cout &lt;&lt; "No successor handler" &lt;&lt; std::endl;
    }




As for how your list of handlers should be defined: almost certainly you should just use a list of handlers (i.e. std::list&lt;Handler&gt; — or std::list&lt;std::weak_ptr&lt;Handler&gt;&gt; if you really want to keep your original design's ability to have handlers drop out of the list at random).

I don't think that a Handler ought to have any idea of its parent; unless... do you think that the parent of a given handler is part of its "identity"? For example, in my example above, do you think it does actually make sense that if an Agent's Supervisor dies, the Agent would have no way of contacting his late Supervisor's Boss, so certain requests would go unhandled? If that really is a feature-not-a-bug, then okay.



Lastly, even if everything else about this design were good, it's unsettling how easy it would be for someone to write a Handler class that just dropped messages on the floor.

class Stockboy : public Handler {
public:
    Stockboy(std::shared_ptr&lt;Handler&gt; successor = nullptr) :Handler(successor) {}
    void handle(Event e) override {
        if (std::get&lt;0&gt;(e) == 7) {
            std::cout &lt;&lt; "Stockboy handled the request: " + std::get&lt;1&gt;(e) &lt;&lt; std::endl;
        }
    }
};


IMO, it would be better to take the responsibility for forwarding unhandled messages and move that responsibility right out of the Handler class. Give it to a Dispatcher class whose job is to find the right Handler and call it. The Dispatcher might hold a mapping of ints to handlers so that it could find the right recipient quickly; or it might just query each handler in turn until some handler reports success.