typeidx: add type tagged namespacing to queries

This commit is contained in:
Danny Robson 2019-09-04 08:06:29 +10:00
parent 3866249607
commit 077ecf5682
3 changed files with 52 additions and 22 deletions

View File

@ -13,5 +13,38 @@ main (int, char**)
tap.expect_eq (cruft::typeidx<float> (), cruft::typeidx<float> (), "equality for float");
tap.expect_neq (cruft::typeidx<int> (), cruft::typeidx<float> (), "inequality for int/float");
struct tag_a {};
struct tag_b {};
// Register an unequal number of types (that don't include f32) to each
// tag before we get to testing in the expectation that will force f32 to
// be different in the following tests.
cruft::typeidx<i16, tag_a> ();
cruft::typeidx<i32, tag_a> ();
cruft::typeidx<i08, tag_b> ();
cruft::typeidx<i16, tag_b> ();
cruft::typeidx<i32, tag_b> ();
// We test using f32 rather than int because we're pretty sure it's not
// going to have the first index (and hence give us false results) given
// int was registered first just above here.
tap.expect_neq (
cruft::typeidx<f32,tag_a> (),
cruft::typeidx<f32> (),
"inequality for f32/f32, tag_a"
);
tap.expect_neq (
cruft::typeidx<f32,tag_a> (),
cruft::typeidx<f32,tag_b> (),
"inequality for f32/f32, tag_a/tag_b"
);
tap.expect_neq (
cruft::typeidx<f32,tag_a> (),
cruft::typeidx<f32, tag_b> (),
"equality for f32/f32, tag_a/tag_a"
);
return tap.status ();
}

View File

@ -7,21 +7,3 @@
*/
#include "typeidx.hpp"
#include <atomic>
///////////////////////////////////////////////////////////////////////////////
static std::atomic<int> counter;
//-----------------------------------------------------------------------------
int
cruft::detail::typeidx_next ()
{
// We can't return zero, but we want to optimise access to the static
// (which means we can't have it locally due to initialisation locking).
//
// Ensure we use pre-increment so that we can utilise zero static
// initialisation instead.
return ++counter;
}

View File

@ -8,12 +8,22 @@
#pragma once
#include <atomic>
#include <cstdint>
namespace cruft {
namespace detail { int typeidx_next (void); }
namespace detail {
template <typename TagT>
int typeidx_next (void)
{
static std::atomic<int> counter;
return ++counter;
}
}
/// Return a globally unique runtime ID for a given type.
/// Return a globally unique runtime ID for a given type (namespaced by a
/// tag type).
///
/// This is intended to be used as a lightweight type check for variants
/// and such without requiring RTTI.
@ -28,11 +38,16 @@ namespace cruft {
/// The range of identifiers is _probably_ contiguous. This should not
/// be relied upon for correctness, but may be used for performance
/// concerns.
template <typename T>
///
/// \tparam T The type to register-and-retrieve the ID for
/// \tparam TagT A namespacing type; different tags will have different
/// sets of IDs. The default Tag is void.
/// \return The unique ID of the type
template <typename T, typename TagT = void>
int
typeidx (void)
{
static auto id = detail::typeidx_next ();
static auto id = detail::typeidx_next<TagT> ();
return id;
}
}