I wanted to make a hash function for a class I am writing and I wanted to make the hash function a friend of the class so that I didn't have to write an unnecessary getter method. To do that I followed the accepted answer in this SO post. But I wanted to be able to insert the objects into either std::unordered_set or boost::unordered_set. So I wrote it like this:
#include <iostream>
#include <unordered_set>
#include <boost/functional/hash.hpp>
#include <boost/unordered_set.hpp>
class Vec;
namespace std { // line [c]
    template<>
    struct hash<Vec> {
    public:
        size_t operator()(const Vec &v) const;
    };
}
class Vec {
private:
    std::vector<int> v;
public:
    friend size_t std::hash<Vec>::operator ()(const Vec& v) const; // line [d]
    friend bool operator == (const Vec& lhs, const Vec& rhs) { return lhs.v == rhs.v; }
};
namespace std { // line [e]
    size_t hash<Vec>::operator()(const Vec &v) const {
        return boost::hash<std::vector<int> >()(v.v);
    }
}
int main() {
    Vec v;
    std::unordered_set<Vec> s1; // line [f]
    s1.insert(v); // line [g]
    boost::unordered_set<Vec> s2; // line [a]
    s2.insert(v); // line [b]
}
But I found that I had a long list of errors when trying to compile this. Then when I removed lines [a,b], it compiled and ran as expected. Then, instead of removing lines [a,b], I (1) left them in, (2) removed lines [f,g], and (3) changed lines [c,d,e] to say boost instead of std, again the code would compile properly. Finally, I tried making a duplicate declaration of the hash struct in the boost namespace:
#include <iostream>
#include <unordered_set>
#include <boost/functional/hash.hpp>
#include <boost/unordered_set.hpp>
class Vec;
namespace std {
    template<>
    struct hash<Vec> {
    public:
        size_t operator()(const Vec &v) const;
    };
}
// new: {
namespace boost {
    template<>
    struct hash<Vec> {
    public:
        size_t operator()(const Vec &v) const;
    };
}
// }
class Vec {
private:
    std::vector<int> v;
public:
    friend size_t std::hash<Vec>::operator ()(const Vec& v) const;
    // new: {
    friend size_t boost::hash<Vec>::operator ()(const Vec& v) const;
    // }
    friend bool operator == (const Vec& lhs, const Vec& rhs) { return lhs.v == rhs.v; }
};
namespace std {
    size_t hash<Vec>::operator()(const Vec &v) const {
        return boost::hash<std::vector<int> >()(v.v);
    }
}
// new: {
namespace boost {
    size_t hash<Vec>::operator()(const Vec &v) const {
        return boost::hash<std::vector<int> >()(v.v);
    }
}
// }
int main() {
    Vec v;
    std::unordered_set<Vec> s1;
    s1.insert(v);
    boost::unordered_set<Vec> s2;
    s2.insert(v);
}
My question is: why do I have to make a hash function in both the std and boost namespace to get it to work? I would say that I have an intuition for why, but I would like a very detailed explanation. And I would like any alternative solutions that would fix the fact that there is a lot of duplicate code in the above code segment (but not something like boost::unordered_set<Vec, my_vec_class_hash> because I want it to be "automatic").
 
    