Add template type checking for EventMetric.
Add template var arg type checking for EventMetric. This change adds some type checking for the variable argument EventMetric which assures that there are no mismatches between the definition of an EventMetric instance and the overloaded constructor. This is a merge from wvgerrit/28424. BUG: 34846989 Test: Manually verified appropriate compile time errors. Change-Id: I3e501abf76b78211f9cef19960ef11c179a0ff93
This commit is contained in:
@@ -238,20 +238,57 @@ inline void AppendFieldNames(std::vector<std::string>* field_name_vector,
|
||||
va_end(field_names);
|
||||
}
|
||||
|
||||
// These helper methods and FirstUnusedType assure that there is no mismatch
|
||||
// between the specified types for EventMetrics and the constructors and
|
||||
// methods used for the specializations.
|
||||
template <bool>
|
||||
struct CompileAssert {};
|
||||
#define COMPILE_ASSERT(expr, msg) \
|
||||
typedef impl::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
|
||||
|
||||
template <typename T> struct is_unused { static const bool value = false; };
|
||||
template <> struct is_unused<Unused> { static const bool value = true; };
|
||||
|
||||
template <typename F1, typename F2, typename F3, typename F4>
|
||||
class FirstUnusedType {
|
||||
static const bool a = is_unused<F1>::value;
|
||||
static const bool b = is_unused<F2>::value;
|
||||
static const bool c = is_unused<F3>::value;
|
||||
static const bool d = is_unused<F4>::value;
|
||||
// Check that all types after the first Unused are also Unused.
|
||||
COMPILE_ASSERT(a <= b, Invalid_Unused_At_Position_2);
|
||||
COMPILE_ASSERT(b <= c, Invalid_Unused_At_Position_3);
|
||||
COMPILE_ASSERT(c <= d, Invalid_Unused_At_Position_4);
|
||||
|
||||
public:
|
||||
static const int value = 5 - (a + b + c + d);
|
||||
};
|
||||
|
||||
// Asserts that no Unused types exist before N; after N, are all Unused types.
|
||||
#define ASSERT_METRIC_UNUSED_START_FROM(N) \
|
||||
COMPILE_ASSERT((\
|
||||
impl::FirstUnusedType<F1, F2, F3, F4>::value) == N, \
|
||||
Unused_Start_From_##N)
|
||||
|
||||
} // namespace impl
|
||||
|
||||
// Overloaded template constructor implementations for EventMetric.
|
||||
template<typename F1, typename F2, typename F3, typename F4>
|
||||
EventMetric<F1, F2, F3, F4>::EventMetric(
|
||||
const std::string& metric_name)
|
||||
: BaseEventMetric(metric_name) {}
|
||||
: BaseEventMetric(metric_name) {
|
||||
ASSERT_METRIC_UNUSED_START_FROM(1);
|
||||
}
|
||||
|
||||
template<typename F1, typename F2, typename F3, typename F4>
|
||||
EventMetric<F1, F2, F3, F4>::EventMetric(
|
||||
const std::string& metric_name,
|
||||
const char* field_name)
|
||||
: BaseEventMetric(metric_name) {
|
||||
impl::AppendFieldNames(&field_names_, 1, field_name);
|
||||
ASSERT_METRIC_UNUSED_START_FROM(2);
|
||||
impl::AppendFieldNames(&field_names_,
|
||||
impl::FirstUnusedType<F1, F2, F3, F4>::value - 1,
|
||||
field_name);
|
||||
}
|
||||
template<typename F1, typename F2, typename F3, typename F4>
|
||||
EventMetric<F1, F2, F3, F4>::EventMetric(
|
||||
@@ -259,7 +296,10 @@ EventMetric<F1, F2, F3, F4>::EventMetric(
|
||||
const char* field_name1,
|
||||
const char* field_name2)
|
||||
: BaseEventMetric(metric_name) {
|
||||
impl::AppendFieldNames(&field_names_, 2, field_name1, field_name2);
|
||||
ASSERT_METRIC_UNUSED_START_FROM(3);
|
||||
impl::AppendFieldNames(&field_names_,
|
||||
impl::FirstUnusedType<F1, F2, F3, F4>::value - 1,
|
||||
field_name1, field_name2);
|
||||
}
|
||||
template<typename F1, typename F2, typename F3, typename F4>
|
||||
EventMetric<F1, F2, F3, F4>::EventMetric(
|
||||
@@ -268,8 +308,10 @@ EventMetric<F1, F2, F3, F4>::EventMetric(
|
||||
const char* field_name2,
|
||||
const char* field_name3)
|
||||
: BaseEventMetric(metric_name) {
|
||||
ASSERT_METRIC_UNUSED_START_FROM(4);
|
||||
impl::AppendFieldNames(&field_names_,
|
||||
3, field_name1, field_name2, field_name3);
|
||||
impl::FirstUnusedType<F1, F2, F3, F4>::value - 1,
|
||||
field_name1, field_name2, field_name3);
|
||||
}
|
||||
template<typename F1, typename F2, typename F3, typename F4>
|
||||
EventMetric<F1, F2, F3, F4>::EventMetric(
|
||||
@@ -279,8 +321,10 @@ EventMetric<F1, F2, F3, F4>::EventMetric(
|
||||
const char* field_name3,
|
||||
const char* field_name4)
|
||||
: BaseEventMetric(metric_name) {
|
||||
ASSERT_METRIC_UNUSED_START_FROM(5);
|
||||
impl::AppendFieldNames(&field_names_,
|
||||
4, field_name1, field_name2,
|
||||
impl::FirstUnusedType<F1, F2, F3, F4>::value - 1,
|
||||
field_name1, field_name2,
|
||||
field_name3, field_name4);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user