Namensräume
Varianten
Aktionen

std::common_type

Von cppreference.com
< cpp‎ | types
 
 
Metaprogrammierungsbibliothek
Typmerkmale
Typkategorien
(C++11)
(C++11)(DR*)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11) 
(C++11)
(C++11)
Typeneigenschaften
(C++11)
(C++11)
(C++14)
(C++11)(deprecated in C++26)
(C++11)(bis C++20*)
(C++11)(veraltet in C++20)
(C++11)
Typmerkmalskonstanten
Metafunktionen
(C++17)
Unterstützte Operationen
Beziehungen und Eigenschaftsabfragen
Typmodifikationen
(C++11)(C++11)(C++11)
Typentransformationen
(C++11)(veraltet in C++23)
(C++11)(veraltet in C++23)
(C++11)
(C++11)(bis C++20*)(C++17)

(C++11)
common_type
(C++11)
(C++11)
(C++17)
Rationale Arithmetik zur Compilezeit
Ganzzahlsequenzen zur Compilezeit
 
Definiert in der Kopfdatei <type_traits>
template< class... T >
struct common_type;
(seit C++11)

Ermittelt den gemeinsamen Typ aller Typen T..., d.h. einen Typ, zu dem alle T... explizit konvertiert werden können. Wenn ein solcher Typ existiert (wie nach den folgenden Regeln bestimmt), bezeichnet das Element type diesen Typ. Andernfalls gibt es kein Element type.

  • Wenn sizeof...(T) null ist, gibt es kein Element type.
  • Wenn sizeof...(T) eins ist (d. h. T... enthält nur einen Typ T0), bezeichnet das Element type denselben Typ wie std::common_type<T0, T0>::type, falls dieser existiert; andernfalls gibt es kein Element 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 Element type denselben Typ wie std::common_type<std::decay<T1>::type, std::decay<T2>::type>::type, falls dieser existiert; wenn nicht, gibt es kein Element type;
  • Andernfalls, wenn eine Benutzerspezialisierung für std::common_type<T1, T2> existiert, wird diese Spezialisierung verwendet;
  • Andernfalls, wenn std::decay<decltype(false ? std::declval<T1>() : std::declval<T2>())>::type ein gültiger Typ ist, bezeichnet das Element type diesen Typ, siehe den bedingten Operator;
(seit C++20)
  • Andernfalls gibt es kein Element type.
  • Wenn sizeof...(T) größer als zwei ist (d. h. T... besteht aus den Typen T1, T2, R...), dann, wenn std::common_type<T1, T2>::type existiert, bezeichnet das Element type std::common_type<typename std::common_type<T1, T2>::type, R...>::type, wenn ein solcher Typ existiert. In allen anderen Fällen gibt es kein Element type.

Wenn ein Typ im Parameterpaket T kein vollständiger Typ ist (möglicherweise cv-qualifiziert) void oder ein Array unbekannter Bindung, ist das Verhalten undefiniert.

Wenn eine Instanziierung einer Vorlage davon 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.

Inhalt

[bearbeiten] Verschachtelte Typen

Name Definition
type der gemeinsame Typ für alle T

[bearbeiten] Hilfstypen

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

[bearbeiten] Spezialisierungen

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

  • Mindestens einer der Typen T1 und T2 von einem benutzerspezifizierten Typ abhängt, und
  • std::decay eine Identitätsoperation für sowohl T1 als auch T2 ist.

Wenn eine solche Spezialisierung ein Element namens type hat, muss dieses ein öffentliches und eindeutiges Element sein, das einen cv-unqualifizierten Nicht-Referenz-Typ bezeichnet, zu dem 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 unter Verstoß gegen diese Regeln hinzufügt, hat undefiniertes Verhalten.

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

Die folgenden Spezialisierungen werden bereits von der Standardbibliothek bereitgestellt

spezialisiert den std::common_type Trait
(Klassentemplate-Spezialisierung) [edit]
spezialisiert den std::common_type Trait
(Klassentemplate-Spezialisierung) [edit]
ermittelt den gemeinsamen Typ von zwei pairs
(Klassenvorlagenspezialisierung) [edit]
ermittelt den gemeinsamen Typ eines tuple und eines tuple-like Typs
(class template specialization) [bearbeiten]
ermittelt den gemeinsamen Typ eines Iterators und eines angepassten basic_const_iterator-Typs
(Klassenvorlagenspezialisierung) [bearbeiten]

[bearbeiten] Mögliche Implementierung

// primary template (used for zero types)
template<class...>
struct common_type {};
 
// one type
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 implementation:
    // 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> {};
}
 
// two types
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+ types
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...> {};

[bearbeiten] 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.

[bearbeiten] Beispiele

Demonstriert gemischte Arithmetik auf einer vom Programm definierten 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}

[bearbeiten] Fehlerberichte

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

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
LWG 2141 C++11 Der Ergebnistyp des bedingten Operators wurde nicht decay-verarbeitet decay-verarbeitete den Ergebnistyp
LWG 2408 C++11 common_type war nicht SFINAE-freundlich Wurde SFINAE-freundlich gemacht.
LWG 2460 C++11 common_type-Spezialisierungen waren fast unmöglich zu schreiben reduzierte die Anzahl der
benötigten Spezialisierungen

[bearbeiten] Siehe auch

gibt an, dass zwei Typen einen gemeinsamen Typ haben
(Konzept) [bearbeiten]