view C++/Flags.h @ 269:44dcc198bf0c

Dynlib (test): Add dl library for Linux
author David Demelier <markand@malikania.fr>
date Fri, 17 Oct 2014 14:20:00 +0200
parents a9946b5ca0cb
children
line wrap: on
line source

/*
 * Flags.h -- safe wrapper for enum flags
 *
 * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _FLAGS_H_
#define _FLAGS_H_

/**
 * @file Flags.h
 * @brief Provide template class Flags and operators for enum classes
 */

#include <type_traits>

/**
 * @class Flags
 * @brief Wrapper that store enum flags
 *
 * This class is used to store an enum and make bitwise operations on it. User do not need
 * to supply these operators because they are implemented in the class.
 *
 * This class is very cheap and store the real underlying type from the enum and all functions
 * are inlined.
 */
template <typename Enum, typename Type = std::underlying_type_t<Enum>>
class Flags final {
private:
	Type m_value { 0 };
	
public:
	/**
	 * Construct flags to 0.
	 */
	constexpr Flags() noexcept = default;

	/**
	 * Construct flags with the enum value.
	 *
	 * @param m the mask
	 */
	constexpr Flags(Enum m) noexcept
		: m_value(static_cast<Type>(m))
	{
	}

	/**
	 * Construct flags with the enum value.
	 *
	 * @param m the mask
	 */
	constexpr Flags(Type m) noexcept
		: m_value(m)
	{
	}

	/**
	 * Move constructor.
	 *
	 * @param other the other
	 */
	inline Flags(Flags &&other) noexcept = default;

	/**
	 * Copy constructor.
	 *
	 * @param other the other
	 */
	inline Flags(const Flags &other) noexcept = default;

	/**
	 * Move operator.
	 *
	 * @param other the other
	 */
	inline Flags &operator=(Flags &&other) noexcept = default;

	/**
	 * Copy operator.
	 *
	 * @param other the other
	 */
	inline Flags &operator=(const Flags &other) noexcept = default;

	/**
	 * &= operator.
	 *
	 * @param m the mask
	 * @return *this
	 */
	inline Flags &operator&=(Enum m) noexcept
	{
		m_value &= static_cast<Type>(m);

		return *this;
	}
	
	/**
	 * &= operator.
	 *
	 * @param m the mask
	 * @return *this
	 */
	inline Flags &operator&=(Type m) noexcept
	{
		m_value &= m;

		return *this;
	}

	/**
	 * |= operator.
	 *
	 * @param m the mask
	 * @return *this
	 */
	inline Flags &operator|=(Enum m) noexcept
	{
		m_value |= static_cast<Type>(m);

		return *this;
	}
	
	/**
	 * |= operator.
	 *
	 * @param m the mask
	 * @return *this
	 */
	inline Flags &operator|=(Type m) noexcept
	{
		m_value |= m;

		return *this;
	}

	/**
	 * ^= operator.
	 *
	 * @param m the mask
	 * @return *this
	 */
	inline Flags &operator^=(Enum m) noexcept
	{
		m_value ^= static_cast<Type>(m);

		return *this;
	}
	
	/**
	 * ^= operator.
	 *
	 * @param m the mask
	 * @return *this
	 */
	inline Flags &operator^=(Type m) noexcept
	{
		m_value ^= m;

		return *this;
	}

	/**
	 * & operator.
	 *
	 * @param m the mask
	 * @return & combination
	 */
	constexpr Flags operator&(Enum m) const noexcept
	{
		return m_value & static_cast<Type>(m);
	}

	/**
	 * & operator.
	 *
	 * @param m the mask
	 * @return & combination
	 */
	constexpr Flags operator&(Type m) const noexcept
	{
		return m_value & m;
	}

	/**
	 * | operator.
	 *
	 * @param m the mask
	 * @return | combination
	 */
	constexpr Flags operator|(Enum m) const noexcept
	{
		return m_value | static_cast<Type>(m);
	}
	
	/**
	 * | operator.
	 *
	 * @param m the mask
	 * @return | combination
	 */
	constexpr Flags operator|(Type m) const noexcept
	{
		return m_value | m;
	}

	/**
	 * ^ operator.
	 *
	 * @param m the mask
	 * @return ^ combination
	 */
	constexpr Flags operator^(Enum m) const noexcept
	{
		return m_value & static_cast<Type>(m);
	}

	/**
	 * ^ operator.
	 *
	 * @param m the mask
	 * @return ^ combination
	 */
	constexpr Flags operator^(Type m) const noexcept
	{
		return m_value & m;
	}

	/**
	 * ~ unary operator.
	 *
	 * @return ~
	 */
	constexpr Flags operator~() const noexcept
	{
		return ~m_value;
	}

	/**
	 * Convert to bool. Simply check if value is not 0.
	 *
	 * @return true if value != 0
	 */
	constexpr operator bool() const noexcept
	{
		return m_value != 0;
	}

	/**
	 * Operator !. Simply check if value is 0.
	 *
	 * @return true if value == 0
	 */
	constexpr bool operator!() const noexcept
	{
		return m_value == 0;
	}

	/**
	 * Test comparison with other mask.
	 *
	 * @return true if this value == m
	 */
	constexpr bool operator==(Enum m) const noexcept
	{
		return m_value == static_cast<Type>(m);
	}

	/**
	 * Test comparison with other mask.
	 *
	 * @return true if this value == m
	 */
	constexpr bool operator==(Type m) const noexcept
	{
		return m_value == m;
	}
};

/**
 * Apply & operator on the enum.
 *
 * @param x1 the first value
 * @param x2 the second value
 */
template <typename Value, typename Type = std::enable_if_t<std::is_enum<Value>::value, std::underlying_type_t<Value>>>
constexpr Value operator&(Value x1, Value x2) noexcept
{
	return static_cast<Value>(static_cast<Type>(x1) & static_cast<Type>(x2));
}

/**
 * Apply | operator on the enum.
 *
 * @param x1 the first value
 * @param x2 the second value
 */
template <typename Value, typename Type = std::enable_if_t<std::is_enum<Value>::value, std::underlying_type_t<Value>>>
constexpr Value operator|(Value x1, Value x2) noexcept
{
	return static_cast<Value>(static_cast<Type>(x1) | static_cast<Type>(x2));
}

/**
 * Apply ^ operator on the enum.
 *
 * @param x1 the first value
 * @param x2 the second value
 */
template <typename Value, typename Type = std::enable_if_t<std::is_enum<Value>::value, std::underlying_type_t<Value>>>
constexpr Value operator^(Value x1, Value x2) noexcept
{
	return static_cast<Value>(static_cast<Type>(x1) ^ static_cast<Type>(x2));
}

/**
 * Apply ~ operator on the enum.
 *
 * @param x1 the first value
 * @param x2 the second value
 */
template <typename Value, typename Type = std::enable_if_t<std::is_enum<Value>::value, std::underlying_type_t<Value>>>
constexpr Value operator~(Value x) noexcept
{
	return static_cast<Value>(~static_cast<Type>(x));
}

#endif // !_FLAGS_H_