Here's my own solution, using elements of c++0x that the current version of VS2010 allows for:
#include <iostream>
#include <numeric>
#include <string>
#include <initializer_list>
template <typename enumT>
class FlagSet
{
    public:
        typedef enumT                     enum_type;
        typedef decltype(enumT()|enumT()) store_type;
        // Default constructor (all 0s)
        FlagSet() : FlagSet(store_type(0))
        {
        }
        // Initializer list constructor
        FlagSet(const std::initializer_list<enum_type>& initList)
        {
            // This line didn't work in the initializer list like I thought it would.  It seems to dislike the use of the lambda.  Forbidden, or a compiler bug?
            flags_ = std::accumulate(initList.begin(), initList.end(), store_type(0), [](enum_type x, enum_type y) { return x | y; })
        }
        // Value constructor
        explicit FlagSet(store_type value) : flags_(value)
        {
        }
        // Explicit conversion operator
        operator store_type() const
        {
            return flags_;
        }
        operator std::string() const
        {
            return to_string();
        }
        bool operator [] (enum_type flag) const
        {
            return test(flag);
        }
        std::string to_string() const
        {
            std::string str(size(), '0');
            for(size_t x = 0; x < size(); ++x)
            {
                str[size()-x-1] = (flags_ & (1<<x) ? '1' : '0');
            }
            return str;
        }
        FlagSet& set()
        {
            flags_ = ~store_type(0);
            return *this;
        }
        FlagSet& set(enum_type flag, bool val = true)
        {
            flags_ = (val ? (flags_|flag) : (flags_&~flag));
            return *this;
        }
        FlagSet& reset()
        {
            flags_ = store_type(0);
            return *this;
        }
        FlagSet& reset(enum_type flag)
        {
            flags_ &= ~flag;
            return *this;
        }
        FlagSet& flip()
        {
            flags_ = ~flags_;
            return *this;
        }
        FlagSet& flip(enum_type flag)
        {
            flags_ ^= flag;
            return *this;
        }
        size_t count() const
        {
            // http://www-graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
            store_type bits = flags_;
            size_t total = 0;
            for (; bits != 0; ++total)
            {
                bits &= bits - 1; // clear the least significant bit set
            }
            return total;
        }
        /*constexpr*/ size_t size() const   // constexpr not supported in vs2010 yet
        {
            return sizeof(enum_type)*8;
        }
        bool test(enum_type flag) const
        {
            return (flags_ & flag) > 0;
        }
        bool any() const
        {
            return flags_ > 0;
        }
        bool none() const
        {
            return flags == 0;
        }
    private:
        store_type flags_;
};
template<typename enumT>
FlagSet<enumT> operator & (const FlagSet<enumT>& lhs, const FlagSet<enumT>& rhs)
{
    return FlagSet<enumT>(FlagSet<enumT>::store_type(lhs) & FlagSet<enumT>::store_type(rhs));
}
template<typename enumT>
FlagSet<enumT> operator | (const FlagSet<enumT>& lhs, const FlagSet<enumT>& rhs)
{
    return FlagSet<enumT>(FlagSet<enumT>::store_type(lhs) | FlagSet<enumT>::store_type(rhs));
}
template<typename enumT>
FlagSet<enumT> operator ^ (const FlagSet<enumT>& lhs, const FlagSet<enumT>& rhs)
{
    return FlagSet<enumT>(FlagSet<enumT>::store_type(lhs) ^ FlagSet<enumT>::store_type(rhs));
}
template <class charT, class traits, typename enumT>
std::basic_ostream<charT, traits> & operator << (std::basic_ostream<charT, traits>& os, const FlagSet<enumT>& flagSet)
{
    return os << flagSet.to_string();
}
The interface is modeled after std::bitset. My aim was to be true to the c++ ethos of type safety and minimal (if any) overhead.  I'd welcome any feedback on my implementation.
Here's a minimal example:
#include <iostream>
enum KeyMod
{
    Alt     = 1 << 0,  // 1
    Shift   = 1 << 1,  // 2
    Control = 1 << 2   // 4
};
void printState(const FlagSet<KeyMod>& keyMods)
{
    std::cout << "Alt is "     << (keyMods.test(Alt)     ? "set" : "unset") << ".\n";
    std::cout << "Shift is "   << (keyMods.test(Shift)   ? "set" : "unset") << ".\n";
    std::cout << "Control is " << (keyMods.test(Control) ? "set" : "unset") << ".\n";
}
int main(int argc, char* argv[])
{
    FlagSet<KeyMod> keyMods(Shift | Control);
    printState(keyMods);
    keyMods.set(Alt);
    //keyMods.set(24);    // error - an int is not a KeyMod value
    keyMods.set(Shift);
    keyMods.flip(Control);
    printState(keyMods);
    return 0;
}