Is specializing std::hash outside namespace std unsafe?
No. template<> class std::hash<Sales_data> { ... }; in the global namespace will result in the same as
namespace std {
template<>
class hash<Sales_data> { ... };
}
in the global namespace.
Shouldn't I do this or it is erroneous to do so?
It's fine to do so - but older versions of g++ (versions before version 7 I think, which are still in use) will produce a warning along the lines "warning: specialization of template in different namespace" if you do it like you do in the question. Combined with -Werror this could cause perfectly correct code to fail to compile. I suggest using the namespace { ... } version.
A note on the hash itself: std::hash<any_type_smaller_or_of_equal_size_of_size_t> is likely to be a very poor hash (changing 1 bit won't flip approximately half of the others) in the standard library, returning the same output (bitpattern) as it got as input. This is common because it's extremely fast and fulfills all that's needed when used as a key in a standard container. Every value will get a unique hash, so it's just perfect from that point of view. The problem comes when combining these together. Collisions will be very easy to create - and you want to keep collisions down to a minimum to make lookups in your unordered containers fast. Your XOR operations doesn't change the fact about collisions being plentiful, so I suggest using a function to combine hashes. boost has one that is commonly used (boost::hash_combine).
It looks something like this for 32 bit size_ts (not sure if it's different in different boost versions):
template <class T>
inline void hash_combine(std::size_t& seed, const T& v)
{
    std::hash<T> hasher;
    seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
Example:
namespace stolen { // from boost - use the real boost version to get proper 64 bit hashes
    template <class T>
    inline void hash_combine(std::size_t& seed, const T& v)
    {
        std::hash<T> hasher;
        seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
}
namespace std {
    template <>
    class hash<Sales_data> {
    public:
        using result_type = std::size_t;
        using argument_type = Sales_data;
        result_type operator()(argument_type const& arg) const {
            result_type result = hash<std::string>{}(arg.isbn_);
            stolen::hash_combine(result, arg.nCopySold_);
            stolen::hash_combine(result, arg.revenue_);
            return result;
        }
    };
}
There's also a proposal to add some version of hash_combine into the standard library: hash_combine() Again