Ich habe eine Template-Klasse, die als erstes Template-Argument einen foo * -Zeiger verwendet. Ich möchte eines davon mit einem foo instanziieren, das sich an einer absoluten Adresse befindet:
%Vor%Weiß jemand, ob es möglich ist, ohne auf den Linker zurückzugreifen und FOO_ADDR mit externer Verknüpfung zu definieren?
Dies ist mit dem Keil ARM C / C ++ Compiler Version V5.06 Update 1 (Build 61), ich habe versucht, den C ++ 11-Modus einzuschalten, aber (abgesehen davon, eine Menge neuer Fehler in die System-Header zu werfen) Es hat das Verhalten nicht verändert.
Update: Hier ist die vorgeschlagene Lösung (mit dem echten Code dieses Mal) mit int casts
%Vor%Es ist ziemlich hässlich, aber es funktioniert. Es würde mich interessieren zu hören, ob jemand es verbessern kann?
Die Deklaration bar<(foo*)0x80103400> myFoo;
ist schlecht formatiert, weil nicht-type Template-Argumente ein konstanter Ausdruck aus [temp.arg.nontype]:
Ein Template-Argument für einen Template-Parameter vom Typ soll ein konvertierter konstanter Ausdruck (5.20) vom Typ des Template-Parameters
.
Und das Argument, das Sie übergeben, ist nicht von [expr.const]:
Ein Bedingungsausdruck e ist ein Kernkonstantenausdruck, es sei denn, die Auswertung von e folgt den Regeln des abstrakte Maschine (1.9), würde einen der folgenden Ausdrücke auswerten:
- [...]
- areinterpret_cast
(5.2.10); - [...]
Die Deklaration bar<(foo*)0> huh
funktioniert, da sie keine Umwandlung beinhaltet, sie ist einfach ein Null-Zeiger vom Typ foo*
( 0
ist speziell) und ist daher ein gültiger konstanter Ausdruck.
Sie können die Adresse stattdessen einfach als nicht typspezifischen Parameter übergeben:
%Vor%Das ist machbar.
Aus dem C ++ 11 Standard (Hervorhebung von mir):
14.3.2 Template-Nicht-Typ-Argumente
1 Ein Template-Argument für einen Nicht-Template Template-Parameter muss einer der folgenden sein:
- für einen nicht-type Template-Parameter vom Integral- oder Enumerationstyp ein konvertierter konstanter Ausdruck (5.19) vom Typ des Template-Parameters ; oder
- der Name eines nicht-type Template-Parameters ; oder
- ein konstanter Ausdruck (5.19) , der die Adresse eines Objekts mit statischer Speicherdauer und externer oder interner Verknüpfung oder eine Funktion mit externer oder interner Verknüpfung bezeichnet, einschließlich Funktionsvorlagen und Funktion Template-IDs , aber nicht-statische Klassenmitglieder ausgenommen, ausgedrückt (ignorieren Klammern) als
&
ID-Ausdruck , außer dass die&
weggelassen werden kann, wenn der Name auf a verweist Funktion oder Array und soll entfallen, wenn der entsprechende Template-Parameter eine Referenz ist; oder- ein konstanter Ausdruck, der zu einem Nullzeigerwert (4.10) führt; oder
Beim Kompilieren mit g++ -Wall
erhalte ich den folgenden Fehler:
Es scheint, dass der Compiler erkennen kann, dass 0x80103400
ist nicht die Adresse einer Variablen, es ist nur ein konstanter Ausdruck.
Haben Sie versucht, die Zeigeradresse auf und von uintptr_t
zu werfen, was eine vorzeichenlose Ganzzahl ist, die einen Zeigerwert halten kann?
Der Typ ist in einem Standard-Header <cstdint>
definiert, ist jedoch nur optional. Wenn es in Ihrer Version von C ++ nicht existiert, versuchen Sie stattdessen size_t
.
Ein vollständiges Beispiel würde dann wie folgt aussehen:
%Vor% Der offensichtliche Nachteil besteht darin, dass es beim Template-Parameter keine Typisierung gibt. Sie übergeben einen Wert, der sich hoffentlich auf foo
-Objekt bezieht und nicht auf ein anderes.
Ganz zu schweigen davon, dass wir in der undefinierten Verhaltenswelt sind, was den Standard betrifft ...
Sie scheinen mit der Zeile
kompilieren zu können %Vor%mit mindestens einigen Compilern ( Ссылка )
Wenn Ihr Compiler das Casting im Kontext von constexpr
ablehnt, wie es schlecht formuliert ist (gemäß Barrys Kommentar), können Sie es als reguläre static const
Variable definieren:
Weniger ideal, aber löst dieses Problem hoffentlich.
Erstens, verwende keine C-Style-Modelle. Es macht nicht explizit, was ist.
Zweitens werden Sie feststellen, dass Sie, um eine beliebige Zahl in einen Zeiger zu werfen, reinterpret_cast
verwenden müssen. Diese Art von Cast ist in constexpr-Ausdrücken nicht erlaubt.
Da Vorlagenparameter nur mit konstanten Ausdrücken möglich sind, ist eine beliebige Zahl als Zeiger nicht möglich.
Der Fall, in dem 0 möglich ist, ist, weil 0 in nullptr umwandelbar ist, was ein konstanter Ausdruck ist.