Forum: Compiler & IDEs GCC variable templates + decltype bug?


von Vincent H. (vinci)


Lesenswert?

Grüß euch

Ich hab ein komisches subtiles Problem mit variable templates und 
decltype. Aber vielleicht zuerst etwas Vorgeschichte... Ich nutze 
variable templates als Abkürzung um std::integral_constant Varianten für 
verschiedene Built-In Types zu erzeugen.

Es gibt also zum Beispiel
1
template<uint8_t I>
2
constexpr auto uint8_c{std::integral_constant<uint8_t, I>{}};

(Falls das jemandem bekannt vorkommt, ja, die Bezeichnung ist von Hana 
geklaut ;) )

Soweit so gut. Ich glaub wir sind uns alle einig dass folgendes gilt:
1
std::integral_constant<uint8_t, 42> == uint8_c<42>

Der Compiler (GCC 7.3.0-1) scheint da mit mir einer Meinung zu sein, 
is_same ergibt true und auch die Typenausgabe via boost-typeindex ist 
ident.


Und jetzt wirds irgendwie... komisch.
1
auto t = std::make_tuple(std::make_tuple(uint8_c<42>), 42);
2
auto get_works = get<std::integral_constant<uint8_t, 42>>(t);
3
auto get_doesnt_work = get<decltype(uint8_c<42>)>(t);

Während der erste Aufruf in meine eigene get-Funktion nämlich 
compiliert, tut es der 2. nicht. Der schießt sich mit einer 
static_assertion ab, dass der den Typen nicht findet.

Kennt jemanden einen Bug in Bezug auf decltype und variable templates? 
Da hats doch was oder?


/edit
Achja, die error-msg behauptet auch es is ein 
std:integral_constant<uint8_t, 42>...
1
required from constexpr decltype(auto) get(U&&) [with T = const std::integral_constant<unsigned char, 42>...

Ich versteh die Welt nimma. :)

: Bearbeitet durch User
Beitrag #5360248 wurde vom Autor gelöscht.
von Eric B. (beric)


Lesenswert?

Vincent H. schrieb:
> std::integral_constant<uint8_t, 42> == uint8_c<42>

> auto get_works = get<std::integral_constant<uint8_t, 42>>(t);
> auto get_doesnt_work = get<decltype(uint8_c<42>)>(t);

Das sieht für mich zwar aus wie schwarze Magie, wäre die 
Schlussfolgerung aus den ersten zwei Statements aber folgendes:
1
auto get_doesnt_work = get<uint8_c<42>>(t); // ohne decltype()

(Free free to downvote if this doesn't make sense! ;-D)

auch edit:
> Ich versteh die Welt nimma. :)

Den Anspruch habe ich schon längst aufgegeben :-D

: Bearbeitet durch User
Beitrag #5360265 wurde vom Autor gelöscht.
von Vincent H. (vinci)


Lesenswert?

Manchmal hat man echt einen Knoten im Kopf das gibts gar nicht...

Das Problem war der constexpr-qualifier. Der hat aus uint8_c immer eine 
constexpr gemacht, was sich natürlich am Typ wiederspiegelt. Der Typ 
integral_constant<uint8_t, 42> ist natürlich von sich aus nicht const.

Trotzdem Danke, ich geh mich schämen ;)

von Wilhelm M. (wimalopaan)


Lesenswert?

Ok, das Problem ist gelöst: prima!

Geht mir aber auch manchmal so, dass ich const oder volatile 
Qualifizierungen in der Typinferenz vergesse. Deswegen habe ich es mir 
angewöhnt, womöglich die Qualifizierungen per std::remove_cv, etc. zu 
entfernen bei den entsprechenden Funktionen / Metafunktionen.

Im übrigen ist Vittoreo Romero und andere Kenner fast immer auf 
Stackoverflow unterwegs. Da hast Du bei "interessanten" Fragen recht 
schnell eine stimmige und freundliche(!) Antwort.

von Vincent H. (vinci)


Lesenswert?

Wilhelm M. schrieb:
> Ok, das Problem ist gelöst: prima!
>
> Geht mir aber auch manchmal so, dass ich const oder volatile
> Qualifizierungen in der Typinferenz vergesse. Deswegen habe ich es mir
> angewöhnt, womöglich die Qualifizierungen per std::remove_cv, etc. zu
> entfernen bei den entsprechenden Funktionen / Metafunktionen.
>
> Im übrigen ist Vittoreo Romero und andere Kenner fast immer auf
> Stackoverflow unterwegs. Da hast Du bei "interessanten" Fragen recht
> schnell eine stimmige und freundliche(!) Antwort.

Ja das mach ich meist eh auch und ich versteh auch nicht wieso die 
ganzen Standard Traits es nicht tun. Dinge wie ein std::is_array oder 
ähnliches machen auf "CV-Ref" ja eh keinen Sinn...

Aber bei einem "get" kann es schon sinnvoll sein zwischen const und 
nicht-const zu unterscheiden.

Beitrag #7410586 wurde von einem Moderator gelöscht.
Beitrag #7414683 wurde von einem Moderator gelöscht.
Beitrag #7414941 wurde von einem Moderator gelöscht.
Beitrag #7416082 wurde von einem Moderator gelöscht.
Beitrag #7416525 wurde von einem Moderator gelöscht.
Beitrag #7416773 wurde von einem Moderator gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.