std::experi...common_type(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’– NAME πŸ’–

Bestie, welcome to std::experi...common_type(3) from the C++ Standard Libary manual. The NAME entry is literally std::experimental::ranges::common_type β€” std::experimental::ranges::common_type, same on both sides, and that's iconic. πŸ’…

✨ Synopsis ✨

Defined in header <experimental/ranges/type_traits>.

template< class... T >                               (ranges TS)
struct common_type;

Okay so this template is lowkey the friend who figures out the common type among all the types in T... β€” that is, the type that all of T... can be implicitly converted to. If such a type exists (as determined according to the rules below, no cap), the member type names that type. Otherwise, there is no member type. Also, huge caveat: the behavior is undefined if any of the types in T... is an incomplete type other than (possibly cv-qualified) void. Not me warning you twice. 😭

The vibe check rules are:

  • If sizeof...(T) is zero, there is no member type.
  • If sizeof...(T) is one (i.e., T... contains only one type, T0), the member type names the same type as std::decay_t<T0>.
  • If sizeof...(T) is two (i.e., T... contains exactly two types, T1 and T2):
    • If applying std::decay to at least one of T1 and T2 produces a different type, the member type names the same type as ranges::common_type_t<std::decay_t<T1>, std::decay_t<T2>>, if it exists; if not, there is no member type.
    • Otherwise, (and unless there is a user specialization for ranges::common_type<T1, T2>), if std::common_type_t<T1, T2> is well-formed, then the member type denotes that type.
    • Otherwise, the member type denotes the type std::decay_t<decltype(false ? std::declval<const T1&>() : std::declval<const T2&>())>, if that conditional expression is well-formed; if not, there is no member type.
  • If sizeof...(T) is greater than two (i.e., T... consists of the types T1, T2, R...), then if ranges::common_type_t<T1, T2> exists, the member type denotes ranges::common_type_t<ranges::common_type_t<T1, T2>, R...> if such a type exists. In all other cases, there is no member type.

πŸŽ€ Member types πŸŽ€

One member type, and it's giving main character energy:

  • Name: type β€” Definition: the common type for all T....

πŸ¦‹ Helper types πŸ¦‹

template< class... T >
using common_type_t = typename common_type<T...>::type;

🌸 Specializations 🌸

Users may specialize common_type for types T1 and T2 if:

  • At least one of T1 and T2 depends on a user-defined type, and
  • std::decay is an identity transformation for both T1 and T2.

If such a specialization has a member named type, it must be a public and unambiguous member type that names a cv-unqualified non-reference type to which both T1 and T2 are explicitly convertible. Additionally, ranges::common_type_t<T1, T2> and ranges::common_type_t<T2, T1> must denote the same type.

🚨 A program that adds common_type specializations in violation of these rules has undefined behavior. That's not a vibe. Periodt.

⭐ Notes ⭐

For arithmetic types not subject to promotion, the common type may be viewed as the type of the (possibly mixed-mode) arithmetic expression such as T0() + T1() + ... + Tn().

πŸ“ Example πŸ“

This section is incomplete.

Reason: no example.

🌈 See also 🌈

  • common_type (C++11) β€” determines the common type of a group of types (class template)
  • common_reference β€” determine the common reference type of a set of types (class template)

🏷️ Category 🏷️

  • Todo no example

source/version + date: http://cppreference.com Β· 2024.06.10 Β· page std::experi...common_type(3) β€” bye bestie, go slay some type traits πŸ’…βœ¨

πŸ“¦ where this page comes from