Use C++11 user-defined literals to dispatch valptridx error style

Switch valptridx error style dispatching from using macro pasting to
using C++11 user-defined literals.  This makes the code a bit easier to
read, and removes the need for a C99-conforming preprocessor here, which
should help anyone trying to port to Microsoft Visual Studio.

The new implementation also fixes a limitation of the previous
implementation.  Before, an override that referenced an invalid name
could be silently ignored.  Now, incorrect overrides cause an attempt to
use an undefined instantiation, which fails with a compilation error.
This commit is contained in:
Kp 2020-04-26 17:26:23 +00:00
parent b396445efa
commit 0b070880a7
3 changed files with 234 additions and 113 deletions

View file

@ -22,6 +22,22 @@ template <typename T>
struct strong_typedef;
#endif
/* Use a C++11 user-defined literal to convert a string literal into a
* type, so that it can be used as a template type parameter.
*/
template <typename T, T... v>
struct literal_as_type {};
template <typename T, T... v>
constexpr literal_as_type<T, v...> operator""_literal_as_type();
/* Given two types representing literals, return a type representing the
* concatenation of those literals. This function is never defined, and
* can only be used in unevaluated contexts.
*/
template <typename T, T... a, T... b>
constexpr literal_as_type<T, a..., b...> concatenate(literal_as_type<T, a...> &&, literal_as_type<T, b...> &&);
/* valptridx_specialized_types is never defined, but is specialized to
* define a typedef for a type-specific class suitable for use as a base
* of valptridx<T>.
@ -29,9 +45,91 @@ struct strong_typedef;
template <typename managed_type>
struct valptridx_specialized_types;
class valptridx_untyped_utilities
namespace valptridx_detail {
/* This type is never defined, but explicit specializations of it are
* defined to provide a mapping from literal_as_type<char, 'X'> to
* report_error_style::X, for each member X of report_error_style.
*/
template <typename>
struct literal_type_to_policy;
/* Given a C identifier, stringize it, then pass the string to
* operator""_literal_as_type() to produce a specialization of
* literal_as_type<...>, which can be used as a template type argument.
*/
#define DXX_VALPTRIDX_LITERAL_TO_TYPE2(A) #A##_literal_as_type
#define DXX_VALPTRIDX_LITERAL_TO_TYPE(A) decltype(DXX_VALPTRIDX_LITERAL_TO_TYPE2(A))
/* Generate all the template parameters to one instantiation of
* error_style_dispatch. A macro is used due to the repeated occurrence
* of various boilerplate identifiers.
*/
#define DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(MC,TYPE) \
DXX_VALPTRIDX_LITERAL_TO_TYPE(TYPE), \
DXX_VALPTRIDX_LITERAL_TO_TYPE(DXX_VALPTRIDX_REPORT_ERROR_STYLE_##MC##_), DXX_VALPTRIDX_LITERAL_TO_TYPE(DXX_VALPTRIDX_REPORT_ERROR_STYLE_##MC##_##TYPE), \
DXX_VALPTRIDX_LITERAL_TO_TYPE(DXX_VALPTRIDX_REPORT_ERROR_STYLE_default_), DXX_VALPTRIDX_LITERAL_TO_TYPE(DXX_VALPTRIDX_REPORT_ERROR_STYLE_default_##TYPE), \
DXX_VALPTRIDX_LITERAL_TO_TYPE(DXX_VALPTRIDX_REPORT_ERROR_STYLE_##MC##_default), \
DXX_VALPTRIDX_LITERAL_TO_TYPE(DXX_VALPTRIDX_REPORT_ERROR_STYLE_default) \
class untyped_utilities
{
public:
/* Given a C identifier as PREFIX, and a C type identifier as TYPE,
* generate `concatenate(literal_as_type<PREFIX>,
* literal_as_type<TYPE>)` and `literal_as_type<PREFIX##TYPE>`.
* Compare them for type equality. If `PREFIX##TYPE` matches an
* active macro, it will be expanded to the value of the macro, but
* the concatenation of literal_as_type<PREFIX> and
* literal_as_type<TYPE> will not be expanded. This allows the
* template to detect whether `PREFIX##TYPE` is a defined macro
* (unless `PREFIX##TYPE` is defined as a macro that expands to its
* own name), and choose a branch of `std::conditional` accordingly.
* The true branch is chosen if `PREFIX##TYPE` is _not_ a macro, and
* is implemented by expanding to the third argument. The false
* branch is chosen if `PREFIX##TYPE` is a macro, and is implemented
* as a reference to `literal_type_to_policy`.
*/
#define DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_BRANCH(PREFIX,TYPE,BRANCH_TRUE,...) \
typename std::conditional< \
std::is_same< \
decltype(concatenate( \
std::declval<PREFIX>(), std::declval<TYPE>() \
)), PREFIX##TYPE>::value, \
BRANCH_TRUE, ## __VA_ARGS__, literal_type_to_policy<PREFIX##TYPE> \
>::type
/* Given specializations of `literal_as_type`, find the most
* specific error-reporting style and evaluate to
* `literal_type_to_policy` specialized on that style. Consumers
* can then access `error_style_dispatch<...>::value` to obtain the
* chosen error-reporting style as an enum member of
* report_error_style.
*/
template <typename managed_type,
typename style_qualified_, typename style_qualified_managed_type,
typename style_default_, typename style_default_managed_type,
typename style_qualified_default,
typename style_default>
using error_style_dispatch =
DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_BRANCH(style_qualified_, managed_type,
DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_BRANCH(style_default_, managed_type,
typename std::conditional<
std::is_same<
decltype(
concatenate(
std::declval<style_qualified_>(),
"default"_literal_as_type
)
),
style_qualified_default
>::value,
literal_type_to_policy<style_default>,
literal_type_to_policy<style_qualified_default>
>::type
)
);
#undef DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_BRANCH
/* The style can be selected on a per-const-qualified-type basis at
* compile-time by defining a DXX_VALPTRIDX_REPORT_ERROR_STYLE_*
* macro. See the banner comment by the definition of
@ -183,71 +281,79 @@ protected:
class rebind_policy;
};
/* Map the four reporting styles from their `literal_as_type`
* representation to their `report_error_style` enumerated value.
*/
template <>
struct literal_type_to_policy<decltype("undefined"_literal_as_type)> : std::integral_constant<untyped_utilities::report_error_style, untyped_utilities::report_error_style::undefined>
{
};
template <>
struct literal_type_to_policy<decltype("trap_terse"_literal_as_type)> : std::integral_constant<untyped_utilities::report_error_style, untyped_utilities::report_error_style::trap_terse>
{
};
template <>
struct literal_type_to_policy<decltype("trap_verbose"_literal_as_type)> : std::integral_constant<untyped_utilities::report_error_style, untyped_utilities::report_error_style::trap_verbose>
{
};
template <>
struct literal_type_to_policy<decltype("exception"_literal_as_type)> : std::integral_constant<untyped_utilities::report_error_style, untyped_utilities::report_error_style::exception>
{
};
template <
typename INTEGRAL_TYPE,
std::size_t array_size_value,
valptridx_untyped_utilities::report_error_style report_const_error_value,
valptridx_untyped_utilities::report_error_style report_mutable_error_value
untyped_utilities::report_error_style report_const_error_value,
untyped_utilities::report_error_style report_mutable_error_value
>
class valptridx_specialized_type_parameters : public valptridx_untyped_utilities
class specialized_type_parameters : public untyped_utilities
{
public:
using integral_type = INTEGRAL_TYPE;
static constexpr std::integral_constant<std::size_t, array_size_value> array_size{};
using report_error_uses_exception = std::integral_constant<bool,
report_const_error_value == valptridx_untyped_utilities::report_error_style::exception ||
report_mutable_error_value == valptridx_untyped_utilities::report_error_style::exception
report_const_error_value == untyped_utilities::report_error_style::exception ||
report_mutable_error_value == untyped_utilities::report_error_style::exception
>;
template <typename array_managed_type, typename report_error_exception>
using dispatch_index_mismatch_error = typename valptridx_untyped_utilities::template dispatch_mc_report_error_type<
using dispatch_index_mismatch_error = typename untyped_utilities::template dispatch_mc_report_error_type<
array_managed_type,
report_const_error_value,
report_mutable_error_value,
typename valptridx_untyped_utilities::index_mismatch_trap_verbose,
typename untyped_utilities::index_mismatch_trap_verbose,
report_error_exception
>;
template <typename array_managed_type, typename report_error_exception>
using dispatch_index_range_error = typename valptridx_untyped_utilities::template dispatch_mc_report_error_type<
using dispatch_index_range_error = typename untyped_utilities::template dispatch_mc_report_error_type<
array_managed_type,
report_const_error_value,
report_mutable_error_value,
typename valptridx_untyped_utilities::index_range_trap_verbose,
typename untyped_utilities::index_range_trap_verbose,
report_error_exception
>;
template <typename array_managed_type, typename report_error_exception>
using dispatch_null_pointer_error = typename valptridx_untyped_utilities::template dispatch_mc_report_error_type<
using dispatch_null_pointer_error = typename untyped_utilities::template dispatch_mc_report_error_type<
array_managed_type,
report_const_error_value,
report_mutable_error_value,
typename valptridx_untyped_utilities::null_pointer_trap_verbose,
typename untyped_utilities::null_pointer_trap_verbose,
report_error_exception
>;
};
/* These defines must expand to a value of the form (**comma**, *style*,
* **comma**). They are not required to use the _style_ name as a
* trailing suffix, but that convention makes the code easier to
* understand.
*
* *style* must be a member of
* `valptridx_untyped_utilities::report_error_style`.
*/
#define DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH_undefined , undefined,
#define DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH_trap_terse , trap_terse,
#define DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH_trap_verbose , trap_verbose,
#define DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH_exception , exception,
}
/* If not otherwise defined, set the default reporting style for all
* valptridx errors. The macro value must be equal to the suffix of one
* of the four DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH_* macros above.
* For convenience, those suffixes match the members of
* `report_error_style`.
* of the four members of `report_error_style`.
*
* For finer control, valptridx inspects four values and picks the first
* value defined to a valid style. Invalid styles are ignored and later
* values are searched. Clever use of a constexpr comparison could
* detect invalid styles, but until someone needs such detection, this
* is left as a sharp edge for simplicity.
* defined value. Undefined styles are ignored and later values are
* searched. Invalid values produce a compile-time error.
*
* For const inputs, the four values are:
* - DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_<TYPE>
@ -278,84 +384,13 @@ public:
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_default exception
#endif
#define DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH(A) DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH_##A
/* This approximates the ability to test defined-ness of a macro
* argument, even though `#if defined(A)` cannot portably be used when
* `A` is a macro parameter. A Python function that does the same (but
* more cleanly and safely) as this macro would be written as:
*
* ```
* def DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_DISPATCH(A,B,C,D):
* for candidate in (A, B, C, D):
* if cpp_macro_defined(candidate):
* return cpp_macro_expand(candidate)
* return ''
* ```
*
* Each of the four arguments evaluates, after macro expansion, to one of five values:
* - `undefined`
* - `trap_terse`
* - `trap_verbose`
* - `exception`
* - anything else
*
* Pass each argument to a separate
* DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH. If the argument is one of
* the four recognized values, then after pasting, it will be one of the
* four DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH_* macros, and will
* expand to contain a leading and trailing comma. If it is
* unrecognized, it will not expand[1] and will therefore contain no
* commas. After expansion, the arguments to
* DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_UNPACK_ARGS are:
*
* - 0-or-more garbage non-comma tokens resulting from arguments that
* were "anything else"
* - comma from the first matched argument
* - token from the first matched argument (which will be one of the
* four accepted types)
* - another comma from the first matched argument
* - 0-or-more tokens from later arguments, which may or may not have
* been "anything else" and may or may not include more commas
*
* The call to UNPACK_ARGS then drops everything up to and including the
* first comma from the first matched argument and everything at and
* after the second comma from the first matched argument. It passes
* through the non-comma token from the first matched argument, yielding
* one of the four recognized types.
*
* [1] Assuming no definitions for
* DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH_* other than the four
* above. For proper operation, no other macros should be defined with
* that prefix.
*/
#define DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_DISPATCH(A,B,C,D) \
DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_UNPACK_ARGS( \
DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH(A) \
DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH(B) \
DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH(C) \
DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_BRANCH(D) \
,)
#define DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_UNPACK_ARGS(A,...) \
DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_DROP1(A, ## __VA_ARGS__)
#define DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_DROP1(DROP,TAKE,...) TAKE
#define DXX_VALPTRIDX_DECLARE_SUBTYPE(NS_TYPE,MANAGED_TYPE,INTEGRAL_TYPE,ARRAY_SIZE_VALUE) \
template <> \
struct valptridx_specialized_types<NS_TYPE MANAGED_TYPE> { \
using type = valptridx_specialized_type_parameters< \
using type = valptridx_detail::specialized_type_parameters< \
INTEGRAL_TYPE, \
ARRAY_SIZE_VALUE, \
valptridx_untyped_utilities::report_error_style:: \
DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_DISPATCH( \
DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_##MANAGED_TYPE, \
DXX_VALPTRIDX_REPORT_ERROR_STYLE_default_##MANAGED_TYPE, \
DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_default, \
DXX_VALPTRIDX_REPORT_ERROR_STYLE_default), \
valptridx_untyped_utilities::report_error_style:: \
DXX_VALPTRIDX_INTERNAL_ERROR_STYLE_DISPATCH( \
DXX_VALPTRIDX_REPORT_ERROR_STYLE_mutable_##MANAGED_TYPE, \
DXX_VALPTRIDX_REPORT_ERROR_STYLE_default_##MANAGED_TYPE, \
DXX_VALPTRIDX_REPORT_ERROR_STYLE_mutable_default, \
DXX_VALPTRIDX_REPORT_ERROR_STYLE_default) \
valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(const, MANAGED_TYPE)>::value, \
valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(mutable, MANAGED_TYPE)>::value \
>; \
}

View file

@ -80,12 +80,12 @@ public:
template <
typename INTEGRAL_TYPE,
std::size_t array_size_value,
valptridx_untyped_utilities::report_error_style report_const_error_value,
valptridx_untyped_utilities::report_error_style report_mutable_error_value
valptridx_detail::untyped_utilities::report_error_style report_const_error_value,
valptridx_detail::untyped_utilities::report_error_style report_mutable_error_value
>
constexpr std::integral_constant<std::size_t, array_size_value> valptridx_specialized_type_parameters<INTEGRAL_TYPE, array_size_value, report_const_error_value, report_mutable_error_value>::array_size;
constexpr std::integral_constant<std::size_t, array_size_value> valptridx_detail::specialized_type_parameters<INTEGRAL_TYPE, array_size_value, report_const_error_value, report_mutable_error_value>::array_size;
class valptridx_untyped_utilities::report_error_undefined
class valptridx_detail::untyped_utilities::report_error_undefined
{
public:
__attribute_cold
@ -95,7 +95,7 @@ public:
}
};
class valptridx_untyped_utilities::report_error_trap_terse
class valptridx_detail::untyped_utilities::report_error_trap_terse
{
public:
__attribute_cold
@ -107,7 +107,7 @@ public:
}
};
class valptridx_untyped_utilities::index_mismatch_trap_verbose
class valptridx_detail::untyped_utilities::index_mismatch_trap_verbose
{
public:
__attribute_cold
@ -120,7 +120,7 @@ public:
}
};
class valptridx_untyped_utilities::index_range_trap_verbose
class valptridx_detail::untyped_utilities::index_range_trap_verbose
{
public:
__attribute_cold
@ -133,7 +133,7 @@ public:
}
};
class valptridx_untyped_utilities::null_pointer_trap_verbose
class valptridx_detail::untyped_utilities::null_pointer_trap_verbose
{
public:
__attribute_cold

View file

@ -222,3 +222,89 @@ BOOST_AUTO_TEST_CASE(ptr_convert_check)
})), valptridx_access_override::index_range_exception
);
}
/* For each style selector, set a type. Test that the type is used.
* Reset to a different type. Test that the second type is used. Clear
* the selector, so that any further use is an error.
*
* This combination verifies that the requested style is set, and that
* the match is not an accident. If the first test succeeded because
* the style happened to match for the wrong reason, then redefining the
* style would have no effect, and the second test would fail.
*/
/* Test DXX_VALPTRIDX_REPORT_ERROR_STYLE_default - the final fallback,
* used only when everything else is unset.
*/
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_default
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_default exception
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(const, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::exception);
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(mutable, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::exception);
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_default
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_default undefined
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(const, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::undefined);
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(mutable, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::undefined);
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_default
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_default /* invalid mapping - force an error on use */
/* Test the const/mutable defaults. These are the second lowest
* priority, above only DXX_VALPTRIDX_REPORT_ERROR_STYLE_default.
*/
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_default
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_default trap_terse
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_mutable_default
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_mutable_default trap_verbose
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(const, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::trap_terse);
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(mutable, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::trap_verbose);
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_default
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_default exception
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_mutable_default
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_mutable_default trap_terse
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(const, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::exception);
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(mutable, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::trap_terse);
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_default
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_default
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_mutable_default
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_mutable_default
/* Test the type-specific default. This is the third lowest priority.
*/
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_default_error_report_test undefined
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(const, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::undefined);
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(mutable, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::undefined);
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_default_error_report_test
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_default_error_report_test exception
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(const, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::exception);
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(mutable, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::exception);
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_default_error_report_test
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_default_error_report_test
/* Test the const/mutable type-specific. These are the highest
* priority.
*/
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_error_report_test trap_terse
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_mutable_error_report_test trap_verbose
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(const, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::trap_terse);
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(mutable, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::trap_verbose);
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_error_report_test
#undef DXX_VALPTRIDX_REPORT_ERROR_STYLE_mutable_error_report_test
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_const_error_report_test exception
#define DXX_VALPTRIDX_REPORT_ERROR_STYLE_mutable_error_report_test undefined
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(const, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::exception);
static_assert(valptridx_detail::untyped_utilities::error_style_dispatch<DXX_VALPTRIDX_ERROR_STYLE_DISPATCH_PARAMETERS(mutable, error_report_test)>::value == valptridx_detail::untyped_utilities::report_error_style::undefined);