Skip to content

No common_type between CNL types #1053

@mpusz

Description

@mpusz

What are you trying to do?

int s behave as the following:

int16_t i16 = 42;
static_assert(std::is_same_v<decltype(-i16), int>);
static_assert(std::is_same_v<std::common_type_t<decltype(i16), decltype(-i16)>, int>);

Negation of the short type results in an integral promotion to int. Both of those types have common types.

When I try to do the same for CNL types, the integral promotion happens, but the results do not have a common type with the source type:

using cnl16_t = cnl::scaled_integer<int16_t, cnl::power<-2>>;
using cnlint_t = cnl::scaled_integer<int, cnl::power<-2>>;

cnl16_t cnl16 = 42;
static_assert(std::is_same_v<decltype(-cnl16), cnlint_t>);
// static_assert(std::is_same_v<std::common_type_t<decltype(cnl16), decltype(-cnl16)>, cnlint_t>);  // does not compile - no common type

Repro here: https://godbolt.org/z/W8xrbncch

Is this behavior intentional?

Why does it matter?

It was discovered by the mp-units representation type constraints that, as of today, require the following:

template<typename T, typename S>
concept ScalableWith = requires(const T v, const S s) {
  { v * s / s } -> std::common_with<T>;
  { s * v / s } -> std::common_with<T>;
  { v / s * s } -> std::common_with<T>;
};

template<typename T>
concept Addable = requires(const T a, const T b) {
  { -a } -> std::common_with<T>;
  { a + b } -> std::common_with<T>;
  { a - b } -> std::common_with<T>;
};

template<typename T>
concept WeaklyRegular = std::copyable<T> && std::equality_comparable<T>;

template<typename T>
concept NumberLike = Addable<T> && WeaklyRegular<T>;

template<typename T>
concept BaseScalar = NumberLike<T> && ScalableWith<T, T>;

From the above { -a } -> std::common_with<T>; makes CNL types not satisfy the current mp-units requirements.

I am not claiming that the above constraints are ideal, and feedback is welcome. Anyway, other libraries may do similar things, and they will face the same issues.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions