Skip to content

Instantly share code, notes, and snippets.

@shawndooley
Last active March 9, 2023 15:52
Show Gist options
  • Save shawndooley/23ca121afb4fb1caf50c7383b45e3271 to your computer and use it in GitHub Desktop.
Save shawndooley/23ca121afb4fb1caf50c7383b45e3271 to your computer and use it in GitHub Desktop.
Template that will generate compile time errors if duplicate id's are reused
// Code modified from Boost.Units base_dimension.hpp
// https://www.boost.org/doc/libs/1_81_0/boost/units/base_dimension.hpp
//
// Copyright (C) 2003-2008 Matthias Christian Schabel
// Copyright (C) 2007-2008 Steven Watanabe
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef UNIQUE_INDEX_HPP
#define UNIQUE_INDEX_HPP
#include <boost/mpl/bool.hpp>
#include <boost/mpl/less.hpp>
#include <boost/mpl/long.hpp>
namespace unique {
namespace detail {
struct ordinal_tag {};
struct no {
constexpr no() : dummy() {}
char dummy;
};
struct yes {
no dummy[2];
};
template <bool>
struct ordinal_has_already_been_defined;
template <>
struct ordinal_has_already_been_defined<true> {};
template <>
struct ordinal_has_already_been_defined<false> {
typedef void type;
};
} // namespace detail
template <int N>
struct ordinal {
typedef detail::ordinal_tag tag;
static constexpr long value = N;
};
template <int N>
constexpr long ordinal<N>::value;
/// This must be in namespace boost::units so that ADL
/// will work with friend functions defined inline.
/// INTERNAL ONLY
template <long N>
struct unique_ordinal {};
/// INTERNAL ONLY
template <class T, long N>
struct check_unique_index {
enum { value = sizeof((unique_ordinal<N>())) == sizeof(detail::yes) };
};
template <class Derived, long N,
class = typename detail::ordinal_has_already_been_defined<
check_unique_index<Derived, N>::value>::type>
class unique_index : public ordinal<N> {
public:
/// INTERNAL ONLY
typedef unique_index this_type;
/// Provided for mpl compatability.
typedef Derived type;
private:
/// Check for C++0x. In C++0x, we have to have identical
/// arguments but a different return type to trigger an
/// error. Note that this is only needed for clang as
/// check_unique_index will trigger an error earlier
/// for compilers with less strict name lookup.
/// INTERNAL ONLY
friend constexpr Derived* check_double_register(const unique_ordinal<N>&) {
return (0);
}
};
} // namespace unique
namespace boost {
namespace mpl {
template <>
struct less_impl<unique::detail::ordinal_tag, unique::detail::ordinal_tag> {
template <class T1, class T2>
struct apply : bool_<(T1::value) < (T2::value)> {};
};
} // namespace mpl
} // namespace boost
#endif // UNIQUE_INDEX_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment