CPP2019SSF16

Aus Verteilte Systeme - Wiki
Zur Navigation springen Zur Suche springen

Feature: decltype

  • Eingeführt in: C++11
  • Deprecated seit: -
  • Nicht mehr im Standard seit: -

Syntax

decltype(e)

decltype steht für declared type und gibt in der Programmiersprache C++ den Typ einer Variable, Funktion oder eines Ausdrucks an, die für e eingesetzt werden können. Wobei jeweils der Datentyp und bei Angabe einer Funktion der Returntyp dieser Funktion als Dateityp abgefragt wird und beispielsweise für andere Variablen gesetzt wird. Wichtig hierbei ist, dass bei Ausdrücken, die als e eingesetzt werden können, nicht der Ausdruckswert berechnet wird (siehe hierzu Beispiel unter Code Beispiele: Einfach).

Use Cases

  • decltype wird genutzt, wenn man einen Typ für beispielsweise Return-Values (keine normalen Variablen) benötigt (bspw. bei Funktionstemplates unten)
  • Zusammen mit dem keyword auto ist es möglich generische Funktionstemplates zu schreiben, wobei dann die Rückgabetypen komplett automatisch bestimmt werden.

Motivation für die Einführung

  • Automatische Ableitung von Datentypen, wie bei funktionalen Programmiersprachen
  • In der generischen (funktionalen) Programmierung ist es oft schwierig oder unmöglich, Typen auszudrücken, die von Templateparametern abhängen, insbesondere der Rückgabetyp von Funktionstemplates. (Übersetzt aus: https://en.wikipedia.org/wiki/Decltype) Da die Eingabevariablen sich auch auf die Rückgabevariablen eines Templates auswirken können. (siehe Hierzu: Code-Beispiele: Template und Warnhinweise)
  • In anderen Sprachen existierte bereits ein keyword (typeof), welches automatsich Datentypen ableiten konnte. Für Templates und die generische Programmierung war dieses keyword genau richtig, da hier auch Rückgabewerte von Parametern abhängen, leider wird typeof in C++ schon für eine andere Funktion genutzt, hierbei kam dann decltype als keyword-Bezeichner raus. (Übersetzt aus: https://en.wikipedia.org/wiki/Decltype)

Vorherige Lösungsansätze

  • Durch ein Makro in der BOOST-Library ist es möglich die Funktionsweise von decltype zu erreichen. Dies war auch schon einige Jahre vor C++11 möglich.
//Code-Beispiel zum BOOST-MAKRO
#include <boost/typeof/typeof.hpp>
#include <iostream>
#include <typeinfo>

int main() {
    int a; float b;
    BOOST_TYPEOF(a+b) c = a+b;
    std::cout << typeid(c).name() << std::endl;
}

Warnhinweise

  • Wenn ein Ausdruck innerhalb der runden Klammern des keywords steht, wird dieser nicht berechnet, es wird lediglich der Typ übernommen.
  • decltype benötigt einen Ausdruck, um während der Compilezeit den Datentyp zu bestimmen.
  • Bei der Verwendung von decltype bei Templates kann decltype nie wie folgt verwendet werden, da die Funktionsparameter t und u noch nicht bekannt sind:
#include <stdio.h>
#include <iostream>
using namespace std;

 
template<typename T, typename U>
decltype sub(T t, U u)                // Rückgabetyp hängt von Templateparametern ab
                                      // Rückgabetyp kann seit C++14 abgeleitet werden
{
    return t-u;
}
 
int main() {
    int i= 20;
    double j = 13.3;
    std::cout<<  sub(i,j)<<endl;    
}

/*
Output:
main.cpp:15:10: error: ‘t’ was not declared in this scope
main.cpp:15:12: error: ‘u’ was not declared in this scope
*/

Code-Beispiele: Einfach

int i = 6;
const int&& fun1();
struct A{double x;};
const A* a = new A();

//Typ der angegebenen Variable i wird für i2 übernommen
decltype(i) i2 = 10; 

//Ein RValue-Verweis zu einem const Int
decltype(fun1()) fun2();

//Der Typ des Memberzugriffs ist Double
decltype(a->x) z = 5;

//Der Typ von vi ist vector<int>
std::vector<decltype(i)> vi;

Code-Beispiele: Template

#Template für das Subtrahieren von zwei variablen
#include <stdio.h>
#include <iostream>
using namespace std;

 
template<typename T, typename U>
auto sub(T t, U u) -> decltype(t - u) // Rückgabetyp hängt von Templateparametern ab
                                      // Rückgabetyp kann seit C++14 abgeleitet werden
// auto wird praktisch als Platzhalter für den Wert, der bei decltype rauskommt gesetzt
{
    return t-u;
}
 
int main() {
    int i= 20;
    double j = 13.3;
    std::cout<<  sub(i,j)<<endl;    
}



//Output : 6.7

Präsentationsfolien

Datei:Präsentation decltype.pdf

genutzte Quellen