Another possibility: Use aggregation. Then you do not directly expose the boost.variant to the users of the library, giving you way more freedom for future improvements, and may simplify some debugging tasks by a significant amount.
General Advice:
Aggregation is less tightly coupled than inheritance, therefore better by default, except you know a use-case where you explicitly want to pass your object instance to already existing functions only taking variants. And even than the base class should have been designed with inheritance in mind.
Example for Aggregation for Your Problem:
As far as I understand it, the free functions already exist, and take a variant. Just define a class with the sole data member of the variant, and provide public member functions which do nothing but invoke the already existing free functions with the member variant, like
class variant_wrapper {
boost::variant<A,B> m_variant;
public:
variant_wrapper(...) : m_variant(...) {} // whatever c_tor you need.
void f() { f(m_variant); }
};
Using this approach you abstract away the fact that you are using boost.variant for your implementation (which you already do through a typedef for the library's users), giving you the freedom of later changing that (for optimization or feature extensions or whatever), you can decide to make the values immutable, have a more simple approach to debug accesses to your algorithms, etc. etc..
The disadvantage with the aggregation is that you cannot just pass the wrapper to a static_visitor, but as your users shall not know that there is a variant, and you know to simply pass the member variable, I do not see a big issue here.
Final rant:
C++ is not Java. You need to fix the users of the library...
What you would like to have are C# extension methods; such things do not exist in C++. However, I would not reimplement/implementation-copy boost.variant (maintenance burden), and I would not inherit from it. Use aggregation where possible.