refactor: convertible_impl refactored to convertible + results caching

This commit is contained in:
Mateusz Pusz
2024-11-16 22:11:59 +01:00
parent b00d061ac8
commit 623930ccee
2 changed files with 281 additions and 272 deletions

View File

@ -506,291 +506,290 @@ static_assert(are_ingredients_convertible(dimensionless / area, dimensionless /
// different dimensions
static_assert(convertible_impl(mass, length) == no);
static_assert(convertible_impl(speed, length) == no);
static_assert(convertible_impl(length, speed) == no);
static_assert(convertible_impl(energy, speed) == no);
static_assert(convertible_impl(length, kind_of<time>) == no);
static_assert(convertible_impl(kind_of<time>, length) == no);
static_assert(convertible_impl(energy, kind_of<speed>) == no);
static_assert(convertible_impl(kind_of<speed>, energy) == no);
static_assert(convertible(mass, length) == no);
static_assert(convertible(speed, length) == no);
static_assert(convertible(length, speed) == no);
static_assert(convertible(energy, speed) == no);
static_assert(convertible(length, kind_of<time>) == no);
static_assert(convertible(kind_of<time>, length) == no);
static_assert(convertible(energy, kind_of<speed>) == no);
static_assert(convertible(kind_of<speed>, energy) == no);
// the same types
static_assert(convertible_impl(length, length) == yes);
static_assert(convertible_impl(width, width) == yes);
static_assert(convertible_impl(energy, energy) == yes);
static_assert(convertible_impl(kind_of<length>, kind_of<length>) == yes);
static_assert(convertible_impl(kind_of<energy>, kind_of<energy>) == yes);
static_assert(convertible_impl(get_kind(moment_of_force), get_kind(moment_of_force)) == yes);
static_assert(convertible(length, length) == yes);
static_assert(convertible(width, width) == yes);
static_assert(convertible(energy, energy) == yes);
static_assert(convertible(kind_of<length>, kind_of<length>) == yes);
static_assert(convertible(kind_of<energy>, kind_of<energy>) == yes);
static_assert(convertible(get_kind(moment_of_force), get_kind(moment_of_force)) == yes);
// converting to a different branch
static_assert(convertible_impl(height, width) == cast);
static_assert(convertible_impl(potential_energy, kinetic_energy) == cast);
static_assert(convertible_impl(kinetic_energy, potential_energy) == cast);
static_assert(convertible_impl(rate_of_climb, velocity) == cast);
static_assert(convertible(height, width) == cast);
static_assert(convertible(potential_energy, kinetic_energy) == cast);
static_assert(convertible(kinetic_energy, potential_energy) == cast);
static_assert(convertible(rate_of_climb, velocity) == cast);
// converting to a different kind
static_assert(convertible_impl(frequency, activity) == no);
static_assert(convertible_impl(activity, frequency) == no);
static_assert(convertible_impl(energy, moment_of_force) == no);
static_assert(convertible_impl(energy, torque) == no);
static_assert(convertible_impl(angular_measure, solid_angular_measure) == no);
static_assert(convertible(frequency, activity) == no);
static_assert(convertible(activity, frequency) == no);
static_assert(convertible(energy, moment_of_force) == no);
static_assert(convertible(energy, torque) == no);
static_assert(convertible(angular_measure, solid_angular_measure) == no);
// upcasting same hierarchy branch
static_assert(convertible_impl(width, length) == yes);
static_assert(convertible_impl(path_length, length) == yes);
static_assert(convertible_impl(distance, length) == yes);
static_assert(convertible_impl(distance, path_length) == yes);
static_assert(convertible_impl(special_speed, speed) == yes);
static_assert(convertible_impl(rate_of_climb, speed) == yes);
static_assert(convertible_impl(special_rate_of_climb, speed) == yes);
static_assert(convertible_impl(velocity, speed) == yes);
static_assert(convertible_impl(potential_energy, energy) == yes);
static_assert(convertible_impl(kinetic_energy, energy) == yes);
static_assert(convertible_impl(angular_measure, dimensionless) == yes);
static_assert(convertible(width, length) == yes);
static_assert(convertible(path_length, length) == yes);
static_assert(convertible(distance, length) == yes);
static_assert(convertible(distance, path_length) == yes);
static_assert(convertible(special_speed, speed) == yes);
static_assert(convertible(rate_of_climb, speed) == yes);
static_assert(convertible(special_rate_of_climb, speed) == yes);
static_assert(convertible(velocity, speed) == yes);
static_assert(convertible(potential_energy, energy) == yes);
static_assert(convertible(kinetic_energy, energy) == yes);
static_assert(convertible(angular_measure, dimensionless) == yes);
// upcasting beyond the hierarchy/kind
static_assert(convertible_impl(frequency, inverse(time)) == yes);
static_assert(convertible_impl(speed, length / time) == yes);
static_assert(convertible_impl(speed, length / time) == yes);
static_assert(convertible_impl(velocity, length / time) == yes);
static_assert(convertible_impl(rate_of_climb, length / time) == yes);
static_assert(convertible_impl(rate_of_climb, height / time) == yes);
static_assert(convertible_impl(gravitational_potential_energy, mass* acceleration* length) == yes);
static_assert(convertible(frequency, inverse(time)) == yes);
static_assert(convertible(speed, length / time) == yes);
static_assert(convertible(speed, length / time) == yes);
static_assert(convertible(velocity, length / time) == yes);
static_assert(convertible(rate_of_climb, length / time) == yes);
static_assert(convertible(rate_of_climb, height / time) == yes);
static_assert(convertible(gravitational_potential_energy, mass* acceleration* length) == yes);
// downcasting same hierarchy branch
static_assert(convertible_impl(length, width) == explicit_conversion);
static_assert(convertible_impl(path_length, distance) == explicit_conversion);
static_assert(convertible_impl(length, distance) == explicit_conversion);
static_assert(convertible_impl(path_length, distance) == explicit_conversion);
static_assert(convertible_impl(speed, special_speed) == explicit_conversion);
static_assert(convertible_impl(speed, rate_of_climb) == explicit_conversion);
static_assert(convertible_impl(speed, special_rate_of_climb) == explicit_conversion);
static_assert(convertible_impl(rate_of_climb, special_rate_of_climb) == explicit_conversion);
static_assert(convertible_impl(energy, potential_energy) == explicit_conversion);
static_assert(convertible_impl(energy, kinetic_energy) == explicit_conversion);
static_assert(convertible_impl(dimensionless, rotation) == explicit_conversion);
static_assert(convertible_impl(dimensionless, rotational_displacement) == explicit_conversion);
static_assert(convertible(length, width) == explicit_conversion);
static_assert(convertible(path_length, distance) == explicit_conversion);
static_assert(convertible(length, distance) == explicit_conversion);
static_assert(convertible(path_length, distance) == explicit_conversion);
static_assert(convertible(speed, special_speed) == explicit_conversion);
static_assert(convertible(speed, rate_of_climb) == explicit_conversion);
static_assert(convertible(speed, special_rate_of_climb) == explicit_conversion);
static_assert(convertible(rate_of_climb, special_rate_of_climb) == explicit_conversion);
static_assert(convertible(energy, potential_energy) == explicit_conversion);
static_assert(convertible(energy, kinetic_energy) == explicit_conversion);
static_assert(convertible(dimensionless, rotation) == explicit_conversion);
static_assert(convertible(dimensionless, rotational_displacement) == explicit_conversion);
// downcasting to a different kind
static_assert(convertible_impl(dimensionless, angular_measure) == yes);
static_assert(convertible_impl(dimensionless, kind_of<angular_measure>) == yes);
static_assert(convertible_impl(kind_of<dimensionless>, angular_measure) == yes);
static_assert(convertible_impl(kind_of<dimensionless>, kind_of<angular_measure>) == yes);
static_assert(convertible(dimensionless, angular_measure) == yes);
static_assert(convertible(dimensionless, kind_of<angular_measure>) == yes);
static_assert(convertible(kind_of<dimensionless>, angular_measure) == yes);
static_assert(convertible(kind_of<dimensionless>, kind_of<angular_measure>) == yes);
// derived quantities to type
static_assert(convertible_impl(inverse(frequency), time) == yes);
static_assert(convertible_impl(inverse(period_duration), frequency) == yes);
static_assert(convertible_impl(length * length, area) == yes);
static_assert(convertible_impl(length / time, speed) == yes);
static_assert(convertible_impl(displacement / time, speed) == yes);
static_assert(convertible_impl(displacement / time, velocity) == yes);
static_assert(convertible_impl(height / time, speed) == yes);
static_assert(convertible_impl(height / time, rate_of_climb) == yes);
static_assert(convertible_impl(area / length, length) == yes);
static_assert(convertible_impl(length * length * length, volume) == yes);
static_assert(convertible_impl(area * length, volume) == yes);
static_assert(convertible_impl(volume / length, area) == yes);
static_assert(convertible_impl(volume / area, length) == yes);
static_assert(convertible_impl(volume / length / length, length) == yes);
static_assert(convertible_impl(area * area / length, volume) == yes);
static_assert(convertible_impl(area * (area / length), volume) == yes);
static_assert(convertible_impl(volume / (length * length), length) == yes);
static_assert(convertible_impl(length / speed, time) == yes);
static_assert(convertible_impl(speed * time, length) == yes);
static_assert(convertible_impl(displacement / time / time, acceleration) == yes);
static_assert(convertible_impl(displacement / (time * time), acceleration) == yes);
static_assert(convertible_impl(velocity / time, acceleration) == yes);
static_assert(convertible_impl(velocity / acceleration, time) == yes);
static_assert(convertible_impl(acceleration * time, velocity) == yes);
static_assert(convertible_impl(acceleration * (time * time), displacement) == yes);
static_assert(convertible_impl(mass * pow<2>(length) / pow<2>(time), energy) == yes);
static_assert(convertible_impl(force * length, energy) == yes);
static_assert(convertible_impl(force * position_vector, moment_of_force) == yes);
static_assert(convertible_impl(width * height, area) == yes);
static_assert(convertible_impl(pow<1, 2>(area), length) == yes);
static_assert(convertible_impl(length, pow<1, 2>(area)) == yes);
static_assert(convertible_impl(mass * acceleration_of_free_fall * height, gravitational_potential_energy) == yes);
static_assert(convertible_impl(mass * pow<2>(length) / pow<2>(time), kinetic_energy) == yes);
static_assert(convertible(inverse(frequency), time) == yes);
static_assert(convertible(inverse(period_duration), frequency) == yes);
static_assert(convertible(length * length, area) == yes);
static_assert(convertible(length / time, speed) == yes);
static_assert(convertible(displacement / time, speed) == yes);
static_assert(convertible(displacement / time, velocity) == yes);
static_assert(convertible(height / time, speed) == yes);
static_assert(convertible(height / time, rate_of_climb) == yes);
static_assert(convertible(area / length, length) == yes);
static_assert(convertible(length * length * length, volume) == yes);
static_assert(convertible(area * length, volume) == yes);
static_assert(convertible(volume / length, area) == yes);
static_assert(convertible(volume / area, length) == yes);
static_assert(convertible(volume / length / length, length) == yes);
static_assert(convertible(area * area / length, volume) == yes);
static_assert(convertible(area * (area / length), volume) == yes);
static_assert(convertible(volume / (length * length), length) == yes);
static_assert(convertible(length / speed, time) == yes);
static_assert(convertible(speed * time, length) == yes);
static_assert(convertible(displacement / time / time, acceleration) == yes);
static_assert(convertible(displacement / (time * time), acceleration) == yes);
static_assert(convertible(velocity / time, acceleration) == yes);
static_assert(convertible(velocity / acceleration, time) == yes);
static_assert(convertible(acceleration * time, velocity) == yes);
static_assert(convertible(acceleration * (time * time), displacement) == yes);
static_assert(convertible(mass * pow<2>(length) / pow<2>(time), energy) == yes);
static_assert(convertible(force * length, energy) == yes);
static_assert(convertible(force * position_vector, moment_of_force) == yes);
static_assert(convertible(width * height, area) == yes);
static_assert(convertible(pow<1, 2>(area), length) == yes);
static_assert(convertible(length, pow<1, 2>(area)) == yes);
static_assert(convertible(mass * acceleration_of_free_fall * height, gravitational_potential_energy) == yes);
static_assert(convertible(mass * pow<2>(length) / pow<2>(time), kinetic_energy) == yes);
// additional dimensionless remainder
static_assert(convertible_impl(length / speed, time) == yes);
static_assert(convertible(length / speed, time) == yes);
// derived quantities to more constrained type
static_assert(convertible_impl(inverse(time), frequency) == explicit_conversion);
static_assert(convertible_impl(length / time / time, acceleration) == explicit_conversion);
static_assert(convertible_impl(length / time, velocity) == explicit_conversion);
static_assert(convertible_impl(length / time, rate_of_climb) == explicit_conversion);
static_assert(convertible_impl(acceleration / velocity, frequency) == explicit_conversion);
static_assert(convertible_impl(force * length, torque) == explicit_conversion);
static_assert(convertible_impl(mass * acceleration * length, gravitational_potential_energy) == explicit_conversion);
static_assert(convertible(inverse(time), frequency) == explicit_conversion);
static_assert(convertible(length / time / time, acceleration) == explicit_conversion);
static_assert(convertible(length / time, velocity) == explicit_conversion);
static_assert(convertible(length / time, rate_of_climb) == explicit_conversion);
static_assert(convertible(acceleration / velocity, frequency) == explicit_conversion);
static_assert(convertible(force * length, torque) == explicit_conversion);
static_assert(convertible(mass * acceleration * length, gravitational_potential_energy) == explicit_conversion);
// derived quantities to more specialized type
static_assert(convertible_impl(force * position_vector, torque) == explicit_conversion);
static_assert(convertible_impl(length / time, special_speed) == explicit_conversion);
static_assert(convertible_impl(height / time, special_rate_of_climb) == explicit_conversion);
static_assert(convertible_impl(mass * pow<2>(length) / pow<2>(time), mechanical_energy) == explicit_conversion);
static_assert(convertible_impl(mass * pow<2>(length) / pow<2>(time), potential_energy) == explicit_conversion);
static_assert(convertible_impl(mass * pow<2>(length) / pow<2>(time), gravitational_potential_energy) ==
explicit_conversion);
static_assert(convertible(force * position_vector, torque) == explicit_conversion);
static_assert(convertible(length / time, special_speed) == explicit_conversion);
static_assert(convertible(height / time, special_rate_of_climb) == explicit_conversion);
static_assert(convertible(mass * pow<2>(length) / pow<2>(time), mechanical_energy) == explicit_conversion);
static_assert(convertible(mass * pow<2>(length) / pow<2>(time), potential_energy) == explicit_conversion);
static_assert(convertible(mass * pow<2>(length) / pow<2>(time), gravitational_potential_energy) == explicit_conversion);
// quantities derived from dimensionless
static_assert(convertible_impl(power / power, efficiency) == explicit_conversion);
static_assert(convertible_impl(stress / stress, strain) == explicit_conversion);
static_assert(convertible_impl(stress / stress, efficiency) == explicit_conversion);
static_assert(convertible(power / power, efficiency) == explicit_conversion);
static_assert(convertible(stress / stress, strain) == explicit_conversion);
static_assert(convertible(stress / stress, efficiency) == explicit_conversion);
// specialized dimensionless to dimensionless and back
static_assert(convertible_impl(height / width, dimensionless) == yes);
static_assert(convertible_impl(dimensionless, height / width) == explicit_conversion);
static_assert(convertible(height / width, dimensionless) == yes);
static_assert(convertible(dimensionless, height / width) == explicit_conversion);
// derived with dimensionless remainder after explosion
// TODO revise that
static_assert(convertible_impl(distance / speed, time) == yes);
static_assert(convertible(distance / speed, time) == yes);
// derived quantities to incompatible type
static_assert(convertible_impl(height / time, velocity) == cast);
static_assert(convertible_impl(displacement / time, rate_of_climb) == cast);
static_assert(convertible(height / time, velocity) == cast);
static_assert(convertible(displacement / time, rate_of_climb) == cast);
// type to compatible derived
static_assert(convertible_impl(distance, speed* time) == yes);
static_assert(convertible(distance, speed* time) == yes);
// type to more specialized derived quantity
static_assert(convertible_impl(speed, height / time) == explicit_conversion);
static_assert(convertible_impl(speed, displacement / time) == explicit_conversion);
static_assert(convertible(speed, height / time) == explicit_conversion);
static_assert(convertible(speed, displacement / time) == explicit_conversion);
// type to a derived quantity on a different branch
static_assert(convertible_impl(velocity, height / time) == cast);
static_assert(convertible_impl(rate_of_climb, displacement / time) == cast);
static_assert(convertible(velocity, height / time) == cast);
static_assert(convertible(rate_of_climb, displacement / time) == cast);
// derived quantities requiring explosion to a type
static_assert(convertible_impl(acceleration * time, velocity) == yes);
static_assert(convertible_impl(acceleration * period_duration, velocity) == yes);
static_assert(convertible_impl(velocity * time / period_duration, velocity) == yes);
static_assert(convertible_impl(mass * acceleration_of_free_fall * height / weight, height) == yes);
static_assert(convertible(acceleration * time, velocity) == yes);
static_assert(convertible(acceleration * period_duration, velocity) == yes);
static_assert(convertible(velocity * time / period_duration, velocity) == yes);
static_assert(convertible(mass * acceleration_of_free_fall * height / weight, height) == yes);
// derived quantities to more generic derived compatible type
static_assert(convertible_impl(inverse(width * height), inverse(area)) == yes);
static_assert(convertible_impl(path_length * distance, pow<2>(path_length)) == yes);
static_assert(convertible(inverse(width * height), inverse(area)) == yes);
static_assert(convertible(path_length * distance, pow<2>(path_length)) == yes);
// derived to compatible derived
static_assert(convertible_impl(inverse(length * length), inverse(area)) == yes);
static_assert(convertible_impl(velocity * time, acceleration* pow<2>(time)) == yes);
static_assert(convertible_impl(height / period_duration, length / time) == yes);
static_assert(convertible_impl(height / width, length / length) == yes);
static_assert(convertible_impl(height * width, length* length) == yes);
static_assert(convertible_impl(inverse(path_length * distance), inverse(pow<2>(path_length))) == yes);
static_assert(convertible(inverse(length * length), inverse(area)) == yes);
static_assert(convertible(velocity * time, acceleration* pow<2>(time)) == yes);
static_assert(convertible(height / period_duration, length / time) == yes);
static_assert(convertible(height / width, length / length) == yes);
static_assert(convertible(height * width, length* length) == yes);
static_assert(convertible(inverse(path_length * distance), inverse(pow<2>(path_length))) == yes);
static_assert(convertible_impl(volume * length, pow<2>(area)) == yes);
static_assert(convertible_impl(pow<4>(length), pow<2>(area)) == yes);
static_assert(convertible_impl(pow<2>(radius), pow<2>(length)) == yes);
static_assert(convertible(volume * length, pow<2>(area)) == yes);
static_assert(convertible(pow<4>(length), pow<2>(area)) == yes);
static_assert(convertible(pow<2>(radius), pow<2>(length)) == yes);
// derived to more specialized derived
static_assert(convertible_impl(length / time, height / period_duration) == explicit_conversion);
static_assert(convertible_impl(length * length, height* width) == explicit_conversion);
static_assert(convertible(length / time, height / period_duration) == explicit_conversion);
static_assert(convertible(length * length, height* width) == explicit_conversion);
// derived to incompatible specialized derived
static_assert(convertible_impl(height / time, distance / time) == cast);
static_assert(convertible(height / time, distance / time) == cast);
// when more than one possible combination is present
// TODO revise that
static_assert(convertible_impl(width * height, pow<2>(height)) == cast);
static_assert(convertible_impl(inverse(width * height), inverse(pow<2>(height))) == cast);
static_assert(convertible_impl(width * distance, path_length* width) == yes);
static_assert(convertible_impl(height * distance, path_length* height) == cast);
static_assert(convertible_impl(width * length, length* height) == explicit_conversion);
static_assert(convertible_impl(length * distance, path_length* height) == cast);
static_assert(convertible_impl(width * distance, width* path_length) == yes);
static_assert(convertible_impl(length * distance, height* path_length) == cast);
static_assert(convertible(width * height, pow<2>(height)) == cast);
static_assert(convertible(inverse(width * height), inverse(pow<2>(height))) == cast);
static_assert(convertible(width * distance, path_length* width) == yes);
static_assert(convertible(height * distance, path_length* height) == cast);
static_assert(convertible(width * length, length* height) == explicit_conversion);
static_assert(convertible(length * distance, path_length* height) == cast);
static_assert(convertible(width * distance, width* path_length) == yes);
static_assert(convertible(length * distance, height* path_length) == cast);
// kind to its type
static_assert(convertible_impl(kind_of<length>, length) == yes);
static_assert(convertible_impl(kind_of<length>, width) == yes);
static_assert(convertible_impl(kind_of<length>, position_vector) == yes);
static_assert(convertible_impl(kind_of<frequency>, frequency) == yes);
static_assert(convertible_impl(kind_of<speed>, velocity) == yes);
static_assert(convertible_impl(kind_of<energy>, energy) == yes);
static_assert(convertible_impl(kind_of<energy>, potential_energy) == yes);
static_assert(convertible_impl(kind_of<energy>, kinetic_energy) == yes);
static_assert(convertible_impl(kind_of<dimensionless>, rotation) == yes);
static_assert(convertible_impl(kind_of<dimensionless>, angular_measure) == yes);
static_assert(convertible_impl(kind_of<dimensionless>, rotational_displacement) == yes);
static_assert(convertible(kind_of<length>, length) == yes);
static_assert(convertible(kind_of<length>, width) == yes);
static_assert(convertible(kind_of<length>, position_vector) == yes);
static_assert(convertible(kind_of<frequency>, frequency) == yes);
static_assert(convertible(kind_of<speed>, velocity) == yes);
static_assert(convertible(kind_of<energy>, energy) == yes);
static_assert(convertible(kind_of<energy>, potential_energy) == yes);
static_assert(convertible(kind_of<energy>, kinetic_energy) == yes);
static_assert(convertible(kind_of<dimensionless>, rotation) == yes);
static_assert(convertible(kind_of<dimensionless>, angular_measure) == yes);
static_assert(convertible(kind_of<dimensionless>, rotational_displacement) == yes);
// kind to a type of a different dimension
static_assert(convertible_impl(kind_of<length>, mass) == no);
static_assert(convertible_impl(kind_of<length>, speed) == no);
static_assert(convertible_impl(kind_of<energy>, length) == no);
static_assert(convertible_impl(kind_of<energy>, speed) == no);
static_assert(convertible(kind_of<length>, mass) == no);
static_assert(convertible(kind_of<length>, speed) == no);
static_assert(convertible(kind_of<energy>, length) == no);
static_assert(convertible(kind_of<energy>, speed) == no);
// kind to a type of another kind but the same dimension
static_assert(convertible_impl(kind_of<energy>, moment_of_force) == no);
static_assert(convertible_impl(kind_of<activity>, frequency) == no);
static_assert(convertible_impl(kind_of<frequency>, activity) == no);
static_assert(convertible(kind_of<energy>, moment_of_force) == no);
static_assert(convertible(kind_of<activity>, frequency) == no);
static_assert(convertible(kind_of<frequency>, activity) == no);
// derived kind to a compatible type
static_assert(convertible_impl(kind_of<length / time>, speed) == yes);
static_assert(convertible_impl(kind_of<length / time>, velocity) == yes);
static_assert(convertible_impl(kind_of<length / pow<2>(time)>, acceleration) == yes);
static_assert(convertible_impl(kind_of<inverse(time)>, frequency) == yes);
static_assert(convertible_impl(kind_of<inverse(time)>, activity) == yes);
static_assert(convertible_impl(kind_of<mass * pow<2>(length) / pow<2>(time)>, energy) == yes);
static_assert(convertible_impl(kind_of<mass * pow<2>(length) / pow<2>(time)>, moment_of_force) == yes);
static_assert(convertible_impl(kind_of<frequency * time / length>, repetency) == yes);
static_assert(convertible(kind_of<length / time>, speed) == yes);
static_assert(convertible(kind_of<length / time>, velocity) == yes);
static_assert(convertible(kind_of<length / pow<2>(time)>, acceleration) == yes);
static_assert(convertible(kind_of<inverse(time)>, frequency) == yes);
static_assert(convertible(kind_of<inverse(time)>, activity) == yes);
static_assert(convertible(kind_of<mass * pow<2>(length) / pow<2>(time)>, energy) == yes);
static_assert(convertible(kind_of<mass * pow<2>(length) / pow<2>(time)>, moment_of_force) == yes);
static_assert(convertible(kind_of<frequency * time / length>, repetency) == yes);
// type to a kind of a different kind
static_assert(convertible_impl(mass, kind_of<length>) == no);
static_assert(convertible_impl(speed, kind_of<length>) == no);
static_assert(convertible_impl(length, kind_of<energy>) == no);
static_assert(convertible_impl(speed, kind_of<energy>) == no);
static_assert(convertible_impl(moment_of_force, kind_of<energy>) == no);
static_assert(convertible_impl(frequency, kind_of<activity>) == no);
static_assert(convertible_impl(activity, kind_of<frequency>) == no);
static_assert(convertible(mass, kind_of<length>) == no);
static_assert(convertible(speed, kind_of<length>) == no);
static_assert(convertible(length, kind_of<energy>) == no);
static_assert(convertible(speed, kind_of<energy>) == no);
static_assert(convertible(moment_of_force, kind_of<energy>) == no);
static_assert(convertible(frequency, kind_of<activity>) == no);
static_assert(convertible(activity, kind_of<frequency>) == no);
// converting type to a kind
static_assert(convertible_impl(length, kind_of<length>) == yes);
static_assert(convertible_impl(width, kind_of<length>) == yes);
static_assert(convertible_impl(frequency, kind_of<frequency>) == yes);
static_assert(convertible_impl(frequency, kind_of<inverse(time)>) == yes);
static_assert(convertible_impl(frequency, kind_of<activity>) == no);
static_assert(convertible_impl(energy, kind_of<energy>) == yes);
static_assert(convertible_impl(potential_energy, kind_of<energy>) == yes);
static_assert(convertible_impl(kinetic_energy, kind_of<energy>) == yes);
static_assert(convertible_impl(rotation, kind_of<dimensionless>) == yes);
static_assert(convertible_impl(angular_measure, kind_of<dimensionless>) == yes);
static_assert(convertible_impl(rotational_displacement, kind_of<dimensionless>) == yes);
static_assert(convertible(length, kind_of<length>) == yes);
static_assert(convertible(width, kind_of<length>) == yes);
static_assert(convertible(frequency, kind_of<frequency>) == yes);
static_assert(convertible(frequency, kind_of<inverse(time)>) == yes);
static_assert(convertible(frequency, kind_of<activity>) == no);
static_assert(convertible(energy, kind_of<energy>) == yes);
static_assert(convertible(potential_energy, kind_of<energy>) == yes);
static_assert(convertible(kinetic_energy, kind_of<energy>) == yes);
static_assert(convertible(rotation, kind_of<dimensionless>) == yes);
static_assert(convertible(angular_measure, kind_of<dimensionless>) == yes);
static_assert(convertible(rotational_displacement, kind_of<dimensionless>) == yes);
// converting derived type to a kind
static_assert(convertible_impl(inverse(time), kind_of<frequency>) == yes);
static_assert(convertible_impl(length / time, kind_of<speed>) == yes);
static_assert(convertible_impl(length / pow<2>(time), kind_of<acceleration>) == yes);
static_assert(convertible(inverse(time), kind_of<frequency>) == yes);
static_assert(convertible(length / time, kind_of<speed>) == yes);
static_assert(convertible(length / pow<2>(time), kind_of<acceleration>) == yes);
// converting kind to a kind
static_assert(convertible_impl(kind_of<dimensionless>, kind_of<angular_measure>) == yes);
static_assert(convertible_impl(kind_of<angular_measure>, kind_of<dimensionless>) == yes);
static_assert(convertible(kind_of<dimensionless>, kind_of<angular_measure>) == yes);
static_assert(convertible(kind_of<angular_measure>, kind_of<dimensionless>) == yes);
// converting derived kind to a kind
static_assert(convertible_impl(kind_of<inverse(time)>, kind_of<frequency>) == yes);
static_assert(convertible_impl(kind_of<length / time>, kind_of<speed>) == yes);
static_assert(convertible_impl(kind_of<length / pow<2>(time)>, kind_of<acceleration>) == yes);
static_assert(convertible(kind_of<inverse(time)>, kind_of<frequency>) == yes);
static_assert(convertible(kind_of<length / time>, kind_of<speed>) == yes);
static_assert(convertible(kind_of<length / pow<2>(time)>, kind_of<acceleration>) == yes);
// converting type to a derived kind
static_assert(convertible_impl(speed, kind_of<length / time>) == yes);
static_assert(convertible_impl(velocity, kind_of<length / time>) == yes);
static_assert(convertible_impl(energy, kind_of<mass * pow<2>(length) / pow<2>(time)>) == yes);
static_assert(convertible_impl(mass_density, kind_of<mass / pow<3>(length)>) == yes);
static_assert(convertible(speed, kind_of<length / time>) == yes);
static_assert(convertible(velocity, kind_of<length / time>) == yes);
static_assert(convertible(energy, kind_of<mass * pow<2>(length) / pow<2>(time)>) == yes);
static_assert(convertible(mass_density, kind_of<mass / pow<3>(length)>) == yes);
// kinds of different dimensions
static_assert(convertible_impl(kind_of<mass>, kind_of<length>) == no);
static_assert(convertible_impl(kind_of<energy>, kind_of<length>) == no);
static_assert(convertible_impl(kind_of<length>, kind_of<energy>) == no);
static_assert(convertible_impl(kind_of<frequency>, kind_of<energy>) == no);
static_assert(convertible(kind_of<mass>, kind_of<length>) == no);
static_assert(convertible(kind_of<energy>, kind_of<length>) == no);
static_assert(convertible(kind_of<length>, kind_of<energy>) == no);
static_assert(convertible(kind_of<frequency>, kind_of<energy>) == no);
// derived quantities to dimensionless
static_assert(convertible_impl(frequency * period_duration, dimensionless) == yes);
static_assert(convertible_impl(frequency * time, dimensionless) == yes);
static_assert(convertible_impl(length / length, dimensionless) == yes);
static_assert(convertible_impl(length / width, dimensionless) == yes);
static_assert(convertible(frequency * period_duration, dimensionless) == yes);
static_assert(convertible(frequency * time, dimensionless) == yes);
static_assert(convertible(length / length, dimensionless) == yes);
static_assert(convertible(length / width, dimensionless) == yes);
static_assert(convertible_impl(efficiency, strain) == cast);
static_assert(convertible(efficiency, strain) == cast);
// quantity character checks
static_assert((displacement / time).character == quantity_character::vector);