Namespaces
Variants

std:: common_type

From cppreference.net
Metaprogramming library
Type traits
Type categories
(C++11)
(C++11) ( DR* )
Type properties
(C++11)
(C++11)
(C++14)
(C++11) (deprecated in C++26)
(C++11) ( until C++20* )
(C++11) (deprecated in C++20)
(C++11)
Type trait constants
Metafunctions
(C++17)
Supported operations
Relationships and property queries
Type modifications
Type transformations
(C++11) (deprecated in C++23)
(C++11) (deprecated in C++23)
(C++11)
(C++11) ( until C++20* ) (C++17)

common_type
(C++11)
(C++11)
(C++17)
Compile-time rational arithmetic
Compile-time integer sequences
Definiert im Header <type_traits>
template < class ... T >
struct common_type ;
(seit C++11)

Bestimmt den gemeinsamen Typ aller Typen T... , also einen Typ, in den alle T... explizit konvertiert werden können. Falls ein solcher Typ existiert (gemäß den nachfolgenden Regeln bestimmt), benennt das Mitglied type diesen Typ. Andernfalls existiert kein Mitglied type .

  • Wenn sizeof... ( T ) null ist, existiert kein Member type .
  • Wenn sizeof... ( T ) eins ist (d.h. T... enthält nur einen Typ T0 ), bezeichnet der Member type denselben Typ wie std :: common_type < T0, T0 > :: type falls dieser existiert; andernfalls existiert kein Member type .
  • Wenn sizeof... ( T ) zwei ist (d.h. T... enthält genau zwei Typen T1 und T2 ),
  • Wenn die Anwendung von std::decay auf mindestens einen der Typen T1 und T2 einen anderen Typ ergibt, bezeichnet das Mitglied type denselben Typ wie std :: common_type < std:: decay < T1 > :: type , std:: decay < T2 > :: type > :: type , falls dieser existiert; falls nicht, gibt es kein Mitglied type ;
  • Andernfalls, falls eine Benutzer-Spezialisierung für std :: common_type < T1, T2 > existiert, wird diese Spezialisierung verwendet;
  • Andernfalls, falls std:: decay < decltype ( false ? std:: declval < T1 > ( ) : std:: declval < T2 > ( ) ) > :: type ein gültiger Typ ist, bezeichnet das Mitglied type diesen Typ, siehe den Bedingungsoperator ;
(seit C++20)
  • Andernfalls gibt es kein Mitglied type .
  • Wenn sizeof... ( T ) größer als zwei ist (d.h., T... besteht aus den Typen T1, T2, R... ), dann bezeichnet das Mitglied type std :: common_type < typename std :: common_type < T1, T2 > :: type , R... > :: type , falls ein solcher Typ existiert. In allen anderen Fällen gibt es kein Mitglied type .

Wenn irgendein Typ in der Parameterpack T kein vollständiger Typ ist, (möglicherweise cv-qualifiziert) void , oder ein Array unbekannter Größe, ist das Verhalten undefiniert.

Wenn eine Instanziierung einer Vorlage oben direkt oder indirekt von einem unvollständigen Typ abhängt und diese Instanziierung ein anderes Ergebnis liefern könnte, wenn dieser Typ hypothetisch vervollständigt würde, ist das Verhalten undefiniert.

Inhaltsverzeichnis

Verschachtelte Typen

Name Definition
type der gemeinsame Typ für alle T

Hilfstypen

template < class ... T >
using common_type_t = typename common_type < T... > :: type ;
(seit C++14)

Spezialisierungen

Benutzer können common_type für die Typen T1 und T2 spezialisieren, falls

  • Mindestens einer von T1 und T2 hängt von einem benutzerdefinierten Typ ab, und
  • std::decay ist eine Identitätstransformation für sowohl T1 als auch T2 .

Falls eine solche Spezialisierung ein Mitglied namens type besitzt, muss es sich um ein öffentliches und eindeutiges Mitglied handeln, das einen cv-unqualifizierten Nicht-Referenz-Typ benennt, in den sowohl T1 als auch T2 explizit konvertierbar sind. Zusätzlich müssen std :: common_type < T1, T2 > :: type und std :: common_type < T2, T1 > :: type denselben Typ bezeichnen.

Ein Programm, das common_type Spezialisierungen hinzufügt, die gegen diese Regeln verstoßen, hat undefiniertes Verhalten.

Beachten Sie, dass das Verhalten eines Programms, das eine Spezialisierung zu irgendeinem anderen Template (außer std::basic_common_reference ) (seit C++20) aus <type_traits> hinzufügt, undefiniert ist.

Die folgenden Spezialisierungen werden bereits von der Standardbibliothek bereitgestellt:

spezialisiert das std::common_type Merkmal
(Klassen-Template-Spezialisierung)
spezialisiert das std::common_type Merkmal
(Klassen-Template-Spezialisierung)
bestimmt den gemeinsamen Typ zweier pair s
(Klassen-Template-Spezialisierung)
bestimmt den gemeinsamen Typ eines tuple und eines tuple-like Typs
(Klassen-Template-Spezialisierung)
bestimmt den gemeinsamen Typ eines Iterators und eines angepassten basic_const_iterator Typs
(Klassen-Template-Spezialisierung)

Mögliche Implementierung

// Primäres Template (verwendet für null Typen)
template<class...>
struct common_type {};
// Ein Typ
template<class T>
struct common_type<T> : common_type<T, T> {};
namespace detail
{
    template<class...>
    using void_t = void;
    template<class T1, class T2>
    using conditional_result_t = decltype(false ? std::declval<T1>() : std::declval<T2>());
    template<class, class, class = void>
    struct decay_conditional_result {};
    template<class T1, class T2>
    struct decay_conditional_result<T1, T2, void_t<conditional_result_t<T1, T2>>>
        : std::decay<conditional_result_t<T1, T2>> {};
    template<class T1, class T2, class = void>
    struct common_type_2_impl : decay_conditional_result<const T1&, const T2&> {};
    // C++11 Implementierung:
    // template<class, class, class = void>
    // struct common_type_2_impl {};
    template<class T1, class T2>
    struct common_type_2_impl<T1, T2, void_t<conditional_result_t<T1, T2>>>
        : decay_conditional_result<T1, T2> {};
}
// Zwei Typen
template<class T1, class T2>
struct common_type<T1, T2> 
    : std::conditional<std::is_same<T1, typename std::decay<T1>::type>::value &&
                       std::is_same<T2, typename std::decay<T2>::type>::value,
                       detail::common_type_2_impl<T1, T2>,
                       common_type<typename std::decay<T1>::type,
                                   typename std::decay<T2>::type>>::type {};
// 3+ Typen
namespace detail
{
    template<class AlwaysVoid, class T1, class T2, class... R>
    struct common_type_multi_impl {};
    template<class T1, class T2, class...R>
    struct common_type_multi_impl<void_t<typename common_type<T1, T2>::type>, T1, T2, R...>
        : common_type<typename common_type<T1, T2>::type, R...> {};
}
template<class T1, class T2, class... R>
struct common_type<T1, T2, R...>
    : detail::common_type_multi_impl<void, T1, T2, R...> {};

Hinweise

Für arithmetische Typen, die keiner Promotion unterliegen, kann der gemeinsame Typ als der Typ des (möglicherweise gemischten) arithmetischen Ausdrucks wie T0 ( ) + T1 ( ) + ... + Tn ( ) betrachtet werden.

Beispiele

Demonstriert gemischte Arithmetik mit einer programmdefinierten Klasse:

#include <iostream>
#include <type_traits>
template<class T>
struct Number { T n; };
template<class T, class U>
constexpr Number<std::common_type_t<T, U>>
    operator+(const Number<T>& lhs, const Number<U>& rhs)
{
    return {lhs.n + rhs.n};
}
void describe(const char* expr, const Number<int>& x)
{
    std::cout << expr << "  is  Number<int>{" << x.n << "}\n";
}
void describe(const char* expr, const Number<double>& x)
{
    std::cout << expr << "  is  Number<double>{" << x.n << "}\n";
}
int main()
{
    Number<int> i1 = {1}, i2 = {2};
    Number<double> d1 = {2.3}, d2 = {3.5};
    describe("i1 + i2", i1 + i2);
    describe("i1 + d2", i1 + d2);
    describe("d1 + i2", d1 + i2);
    describe("d1 + d2", d1 + d2);
}

Ausgabe:

i1 + i2  is  Number<int>{3}
i1 + d2  is  Number<double>{4.5}
d1 + i2  is  Number<double>{4.3}
d1 + d2  is  Number<double>{5.8}

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
LWG 2141 C++11 der Ergebnistyp des bedingten Operators wurde nicht zerfallen zerfiel den Ergebnistyp
LWG 2408 C++11 common_type war nicht SFINAE-freundlich SFINAE-freundlich gemacht
LWG 2460 C++11 common_type Spezialisierungen waren nahezu unmöglich zu schreiben reduzierte die Anzahl der
benötigten Spezialisierungen

Siehe auch

spezifiziert, dass zwei Typen einen gemeinsamen Typ teilen
(Konzept)