Fix scoping of vtkm::CellClassification

The cell classifications were using an unscoped enum to define them. The
problem was that the symbols of the enum littered the `vtkm` namespace
without qualification. For example, it defined `vtkm::NORMAL`, which
could easily collide with some other meaning of normal.

Change the cell classification flags to be scoped within
`vtkm::CellClassification`. This thing behaves mostly like a scoped
enum. You can use the values declared within and reference
`vtkm::CellClassification` as a type itself. However, unlike a scoped
enum, `vtkm::CellClassification` items can automatically be cast to and
from `vtkm::UInt8`.
This commit is contained in:
Kenneth Moreland 2022-03-17 12:56:43 -06:00
parent 4aa81d9e1d
commit ccef4d2dbf
2 changed files with 70 additions and 10 deletions

@ -0,0 +1,12 @@
# Favor scoped `enum`s
Several `enum` declarations were changed from a standard `enum` to a
"scoped" `enum` (i.e. `enum struct`). The advantage of a scoped enum is
that they provide better type safety because they won't be converted
willy-nilly to other types. They also prevent the names they define from
being accessible on the inner scope.
There are some cases where you do want the `enum` to convert to other types
(but still want the scope of the symbols to be contained in the `enum`
type). In this case, we worked around the problem by placing an unscoped
`enum` inside of a standard `struct`.

@ -10,22 +10,70 @@
#ifndef vtk_m_CellClassification_h
#define vtk_m_CellClassification_h
#include <vtkm/Deprecated.h>
#include <vtkm/Types.h>
namespace vtkm
{
enum CellClassification : vtkm::UInt8
/// \brief Bit flags used in ghost arrays to identify what type a cell is.
///
/// `CellClassification` contains several bit flags that determine whether a cell is
/// normal or if it should be treated as duplicated or removed in some way. The flags
/// can be (and should be) treated as `vtkm::UInt8` and or-ed together.
///
class CellClassification
{
NORMAL = 0, //Valid cell
GHOST = 1 << 0, //Ghost cell
INVALID = 1 << 1, //Cell is invalid
UNUSED0 = 1 << 2,
BLANKED = 1 << 3, //Blanked cell in AMR
UNUSED3 = 1 << 4,
UNUSED4 = 1 << 5,
UNUSED5 = 1 << 6,
// Implementation note: An enum would be a natural representation for these flags.
// However, a non-scoped enum leaks the names into the broader namespace and a
// scoped enum is too difficult to convert to the `vtkm::UInt8` we really want to
// treat it as. Thus, use constexpr to define the `vtkm::UInt8`s.
vtkm::UInt8 Flags;
public:
// Use an unscoped enum here, where it will be properly scoped in the class.
// Using unscoped enums in this way is sort of obsolete, but prior to C++17
// a `static constexpr` may require a definition in a .cxx file, and that is
// not really possible for this particular class (which could be used on a GPU).
enum : vtkm::UInt8
{
Normal = 0, //Valid cell
Ghost = 1 << 0, //Ghost cell
Invalid = 1 << 1, //Cell is invalid
Unused0 = 1 << 2,
Blanked = 1 << 3, //Blanked cell in AMR
Unused3 = 1 << 4,
Unused4 = 1 << 5,
Unused5 = 1 << 6,
NORMAL VTKM_DEPRECATED(1.8, "Use vtkm::CellClassification::Normal") = Normal,
GHOST VTKM_DEPRECATED(1.8, "Use vtkm::CellClassification::Ghost") = Ghost,
INVALID VTKM_DEPRECATED(1.8, "Use vtkm::CellClassification::Invalid") = Invalid,
UNUSED0 VTKM_DEPRECATED(1.8) = Unused0,
BLANKED VTKM_DEPRECATED(1.8, "Use vtkm::CellClassification::Blanked") = Blanked,
UNUSED3 VTKM_DEPRECATED(1.8) = Unused3,
UNUSED4 VTKM_DEPRECATED(1.8) = Unused4,
UNUSED5 VTKM_DEPRECATED(1.8) = Unused5,
};
VTKM_EXEC constexpr CellClassification(vtkm::UInt8 flags = vtkm::UInt8{ Normal })
: Flags(flags)
{
}
VTKM_EXEC constexpr operator vtkm::UInt8() const { return this->Flags; }
};
}
// Deprecated scoping.
VTKM_DEPRECATED(1.8, "Use vtkm::CellClassification::Normal.")
constexpr vtkm::CellClassification NORMAL = vtkm::CellClassification::Normal;
VTKM_DEPRECATED(1.8, "Use vtkm::CellClassification::Ghost.")
constexpr vtkm::CellClassification GHOST = vtkm::CellClassification::Ghost;
VTKM_DEPRECATED(1.8, "Use vtkm::CellClassification::Invalid.")
constexpr vtkm::CellClassification INVALID = vtkm::CellClassification::Invalid;
VTKM_DEPRECATED(1.8, "Use vtkm::CellClassification::Blanked.")
constexpr vtkm::CellClassification BLANKED = vtkm::CellClassification::Blanked;
} // namespace vtkm
#endif // vtk_m_CellClassification_h