The static route is not feasible unless there is only one Robot in your program, and an instance of that robot is available statically.
Passing a Robot to the task may be OK, but it might reveal too much information and prohibit task usages with objects other than robots.
A third alternative would be to make an interface-like class for completion notifications, extending it in the Robot, and calling it from the task. Unfortunately, C++ does not make it particularly easy by pushing you into the virtual inheritance territory.
You could adopt a callback approach that is common in POSIX thread libraries (passing a void pointer and a function pointer that takes a void pointer), but that is not too C++-ish.
Finally, if you are using C++11, you have anonymous functions that let you address the issue very gracefully by wrapping both a function and an object on which it operates in a single closure without using an external library, such as boost.
Here is a quick example of the third approach (link to ideone):
#include <iostream>
#include <string>
using namespace std;
class WithNotification {
public:
    virtual void notify()=0;
};
class Robot : public virtual WithNotification {
private:
    string name;
public:
    Robot(const string& n) : name(n) {}
    virtual void notify() {cout << name << " has been notified" << endl; }
};
class Task {
private:
    WithNotification& onFinished;
public:
    Task(WithNotification& f) : onFinished(f) {}
    void run() {
        cout << "The task is running" << endl;
        onFinished.notify();
    }
};
int main() {
    Robot r1("Quick");
    Robot r2("Brown");
    Task t1(r1);
    Task t2(r2);
    t1.run();
    t2.run();
}