Detaillierte Einführung in C++s Decltype

1. Grundlegende Einführung

decltypeist ein neues Schlüsselwort in C++11, um den Typ eines Ausdrucks abzuleiten. Gleiche Funktion wie auto, wird zur automatischen Typableitung zur Kompilierungszeit verwendet. Eingeführt , decltypeweil dies nicht auf alle automatischen Typableitungsszenarien anwendbar ist und die Verwendung autoin einigen Sonderfällen autounpraktisch oder sogar überhaupt nicht möglich ist . decltypeSie können sich den Operator auch einfach als eine andere Form vorstellen sizeof, da keiner von beiden sein Argument tatsächlich auswertet, sondern als Tool zur Kompilierungszeit fungiert.

auto varName = value;
decltype(exp) varName = value;
  • auto=Der Typ der Variablen wird anhand des Anfangswerts auf der rechten Seite abgeleitet , und der Typ der Variablen wird decltypeanhand des Ausdrucks abgeleitet, der nichts mit dem Wert auf der rechten Seite zu tun hat .exp=value
  • autoEs ist erforderlich, dass die Variable initialisiert wird, da autoder Variablentyp anhand des Anfangswerts der Variablen abgeleitet wird. Wenn sie nicht initialisiert ist, kann der Variablentyp nicht abgeleitet werden.
  • Es decltypeist nicht erforderlich und kann daher wie folgt geschrieben werden:
decltype(exp) varName;

Im Prinzip exphandelt es sich nur um einen gewöhnlichen Ausdruck, der in beliebiger komplexer Form vorliegen kann, es muss jedoch gewährleistet sein, expdass das Ergebnis von typisiert ist und nicht sein kann void; if ist eine Funktion , die expeinen Wert von zurückgibt , und das Ergebnis von ist ebenfalls eingegeben wird, führt dies zu Kompilierungsfehlern.voidexpvoid

2. Verschiedene Formen von Decltype

int x = 0;
decltype(x) y = 1;            // y -> int
decltype(x + y) z = 0;        // z -> int
const int& i = x;
decltype(i) j = y;            // j -> const int&
const decltype(z) *p = &z;    // *p -> const int, p -> const int*
decltype(z) *m = &z;          // *m -> int, m -> int*
decltype(m)* n = &m;          // *n -> int*, n -> int**

3. Ableitungsregeln

decltypeDie Ableitungsregeln von lassen sich kurz wie folgt zusammenfassen:

  1. Wenn expes sich um einen Ausdruck handelt, der nicht ()in Klammern steht, um einen Zugriffsausdruck für Klassenmitglieder oder um eine einzelne Variable, decltype(exp)ist der Typ expkonsistent mit .

Codebeispiel:

#include<string> 
#include<iostream>
using namespace std;
 
class A {
    
    
public:
    static int total;
    string name;
    int age;
    float scores;
}
 
int A::total = 0;
 
int main()
{
    
    
	int n = 0;
	const int &r = n;
	A a;
	decltype(n) x = n;           // n 为 int,x 被推导为 int
	decltype(r) y = n;           // r 为 const int &,y 被推导为 const int &
	decltype(A::total)  z = 0;   // total 是类 A 的一个 int 类型的成员变量,z 被推导为 int
	decltype(A.name) url = "www.baidu.com"; // url 为 string 类型
	
	return 0;
}
  1. Wenn expes sich um einen Funktionsaufruf handelt, decltype(exp)stimmt der Typ mit dem Typ des Funktionsrückgabewerts überein.

Codebeispiel:

int& func1(int, char);   // 函数返回值为 int&
int&& func2(void);       // 函数返回值为 int&&
int func3(double);       // 函数返回值为 int
 
const int& func4(int, int, int);  // 函数返回值为 const int&
const int&& func5(void);          // 函数返回值为 const int&&
 
int n = 50;
decltype(func1(100,'A')) a = n; // a 的类型为 int&
decltype(func2()) b = 0;        // b 的类型为 int&&
decltype(func3(10.5)) c = 0;    // c 的类型为 int
 
decltype(func4(1,2,3)) x = n;    // x 的类型为 const int&
decltype(func5()) y = 0;         // y 的类型为 const int&&

expBeim Aufruf einer Funktion sind Klammern und Parameter erforderlich, dies ist jedoch nur eine Formalität und führt den Funktionscode nicht tatsächlich aus.

  1. Wenn expes sich um einen L-Wert handelt oder er ()in Klammern steht, decltype(exp)ist der Typ von expein Verweis auf . Unter der Annahme, dass expder Typ von ist T, dann decltype(exp)ist der Typ von T&.

Codebeispiel:

class A 
{
    
    
public:
   int x;
}
 
int main()
{
    
    
	const A obj;
	decltype(obj.x) a = 0;   // a 的类型为 int
	decltype((obj.x)) b = a; // b 的类型为 int&
	 
	int n = 0, m = 0;
	decltype(m + n) c = 0;     // n + m 得到一个右值,c 的类型为 int
	decltype(n = n + m) d = c; // n = n + m 得到一个左值,d 的类型为 int &
	return 0;
}

L-Wert: die Daten, die nach der Ausführung des Ausdrucks noch vorhanden sind, also persistente Daten; r-Wert bezieht sich auf die Daten, die nach der Ausführung des Ausdrucks nicht mehr vorhanden sind, also temporäre Daten. Eine einfache Möglichkeit zur Unterscheidung besteht darin, die Adresse des Ausdrucks zu verwenden. Wenn der Compiler keinen Fehler meldet, handelt es sich um einen L-Wert, andernfalls um einen R-Wert.

  1. Die statischen Mitglieder der Klasse können verwendet werden auto, die nicht statischen Mitglieder der Klasse können jedoch nicht verwendet werden auto. Wenn Sie den Typ der nicht statischen Mitglieder der Klasse ableiten möchten, können Sie ihn nur verwenden decltype.

Codebeispiel:

template<typename T>
class A
{
    
    
private :
   decltype(T.begin()) m_it;
   // typename T::iterator m_it;   // 这种用法会出错
public:
	void func(T& container)
	{
    
    
	   m_it = container.begin();
	}
};
 
int main()
{
    
    
	const vector<int> v;
	A<const vector<int>> obj;
	obj.func(v);
	return 0;
}

4. Sonstiges

Darüber hinaus kann es in Funktionsvorlagen, Klassenvorlagen und lambdaAusdrücken verwendet werden decltype, um Typen abzuleiten oder Typen zu deklarieren.

Der unten angegebene Beispielcode zeigt die lambdaVerwendung in Ausdrücken decltype:

#include <iostream>

int main()
{
    
    
    int x = 42;
    auto f = [&](decltype(x)& val) {
    
     val += 1; };
    f(x);

    std::cout << "x: " << x << std::endl;  // x: 43

    return 0;
}

In diesem Beispiel wird ein lambdaAusdruck definiert, fdessen Argument decltypeden abgeleiteten Argumenttyp als verwendet int&. Da lambdadie im Ausdruck verwendete Variable sichtbar sein muss, lambdawird sie in der Erfassungsliste vor dem Ausdruck verwendet [&], damit lambdader Ausdruck erfasst x. lambdaSchließlich wird der Ausdruck aufgerufen fund xdie Variable als Argument übergeben, wodurch xder Wert von um eins erhöht wird.

Weitere Informationen finden Sie in diesem Blogbeitrag

Guess you like

Origin blog.csdn.net/m0_51913750/article/details/131003652