Ich frage mich, ob ich das ganze Bit vermeiden kann, wo ich gezwungen bin, eine Zeichenfolge zuzuweisen, um die Verkettung durchzuführen.
Dies geschieht alles zur Kompilierzeit, dh ich beabsichtige, die Zeichenfolge zu erhalten "int****" wenn ich referenziere typename_struct<int****>::name(). (Gehen Sie davon aus, dass ich eine entsprechende Spezialisierung für deklariert habe int die zurückkehrt "int")
Wenn der Code jetzt geschrieben ist, führt der Compiler die Verkettung mit std::string nur während der Kompilierzeit durch? (Ich wäre damit einverstanden) Oder führt ein solcher Aufruf zur Laufzeit zu 4 std::string-basierten Verkettungen? (damit wäre ich nicht einverstanden)
Noch besser wäre es, das Bit zu vermeiden, in dem Sie einen ungültigen Zeiger (auf freigegebenen Speicher) zurückgeben.
– Mike Seymour
16. Juli 2014 um 14:32 Uhr
@MikeSeymour Guter Punkt. Es scheint, als würde man den Rückgabetyp auf setzen char const* ist einfach nicht praktikabel
– Steven Lu
16. Juli 2014 um 14:46 Uhr
std::string verwendet dynamischen Speicher, daher kann ich mir keinen Grund vorstellen, dies beim Kompilierungstyp zu tun, insbesondere nicht für die Leistung.
– Neil Kirk
16. Juli 2014 um 16:50 Uhr
@NeilKirk der Punkt ist, dass ich es nicht verwenden muss std::string
– Steven Lu
16. Juli 2014 um 17:39 Uhr
Einen echten C++-String-Typ zur Kompilierzeit zu haben, wäre ein großartiges Werkzeug, das man im Standard haben könnte, und es ist machbar, aber es ist noch nicht passiert. Diese neue Vorschlag ist aber interessant.
– hellseherisch
16. Juli 2014 um 22:09 Uhr
pw
So etwas könntest du gebrauchen. Alles geschieht zur Kompilierzeit. Spezialisieren Sie base_typename_struct, um Ihre primitiven Typen zu definieren.
Ich denke, es kann eine Möglichkeit geben, automatisch zu drehen int hinein 'i','n','t' mithilfe eines Makros. Vielen Dank
– Steven Lu
16. Juli 2014 um 15:19 Uhr
Das ist großartig, aber ich denke, es ist begrenzt, weil es nicht möglich ist, constexpr-Strings zu verketten, es erlaubt nur das Anhängen einzelner Zeichen. Irgendwelche Ideen, um es etwas mächtiger zu machen, damit ich beliebige Concats machen kann? Marcos Link scheint eine Spur zu sein. Ich glaube, dass es möglich ist, ein Makro zu haben, das (natürlich zur Kompilierzeit) einen Unterindex von a abruft char* String … was wir brauchen, ist etwas, das dauert "int" hinein 'i','n','t'
– Steven Lu
16. Juli 2014 um 17:59 Uhr
Der spezifische Anwendungsfall wäre zB das Erhalten des Strings “int* Array” aus dem Typ int*[]
– Steven Lu
16. Juli 2014 um 18:01 Uhr
@StevenLu, du kannst es mit einem Makro machen: EXPAND("int") => 'i', 'n', 't'. Verwenden BOOST_PP_REPEAT mit irgendeiner Art PushBack<str, c> macht den Trick. Ausarbeitung
– Chris
16. Juli 2014 um 18:10 Uhr
Mit verallgemeinert constexpr Funktionen, wird es praktikabler, a zu verwenden constexpr Klasse, die bei Änderung neue Instanzen zurückgibt (a la reine Funktionen).
– Chris
16. Juli 2014 um 18:16 Uhr
Hedede
Alternativer Weg ohne rekursive Templates (erfordert aber C++14):
Ich bin mir nicht sicher, wonach Sie suchen, aber ich glaube, Sie interessieren sich für eine Kombination aus Typ-ID und Namensentwirrung (welchen Compiler verwenden Sie?)
In gcc wäre es so etwas wie
#include<iostream>
#include <string>
#include <typeinfo>
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
using namespace std;
std::string demangle(const char* name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
// enable c++11 by passing the flag -std=c++11 to g++
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status==0) ? res.get() : name ;
}
template <typename T> struct typename_struct {
static std::string name() {
std::string typeName = typeid(T).name();
return demangle(typeName.c_str());
}
};
int main(){
cout << typename_struct<int****>::name(); // Prints "int****"
return 0;
}
Zu deiner Frage: Das sind sie nicht constexpr Konstrukte, daher erfolgt die Auswertung zur Laufzeit, obwohl die Vorlagenparameter und der Code zur Kompilierzeit instanziiert werden.
Die Verwendung von Vorlagen bedeutet nicht, dass jede darin enthaltene Anweisung zur “Kompilierzeit” ausgeführt und aufgelöst wird.
Ich glaube, Sie können diese ganze Menge Zeug nicht zur Kompilierzeit erreichen, da De-Mangling-Funktionen (ABI-spezifisch) beteiligt sind. Wenn ich Ihre Frage falsch interpretiert habe, lassen Sie es mich bitte wissen.
Richtig, ich kenne mich mit Typeid und Name-Demanbling aus, ich mache das parallel (damit ich es überprüfen kann – es macht normalerweise die Typen von Template-Instanziierungen hässlich). In meinem Projekt hier geht es darum, “Reflexion” auf andere Weise zu erreichen, also versuche ich zu sehen, ob ich Vorlagen definieren kann, um alle Grundlagen abzudecken. Es hat bisher gut funktioniert. Jetzt sagen Sie, dass es sich nicht um constexpr-Konstrukte handelt, weil ich es verwende std::string um die Verkettung zu tun? Gibt es eine Möglichkeit für mich, die Verkettung zur Kompilierzeit zu erzwingen, wenn ich alle diese Vorlagen auch zu constexprs machen kann (wenn das überhaupt Sinn macht)?
– Steven Lu
16. Juli 2014 um 14:57 Uhr
Es ist eigentlich keine große Sache, wenn jede “Zeigerkette” zur Laufzeit eine lineare Zeichenfolgenverkettungsoperation induziert. Hauptsächlich, weil ich das nur für “Kompatibilität” brauche. Die Verwendung dieser verrückten Typen ist in fast allen Fällen nicht ratsam.
– Steven Lu
16. Juli 2014 um 15:00 Uhr
@StevenLu Es gibt mehrere Einschränkungen für constexpr Funktionen, schau mal hier: de.cppreference.com/w/cpp/language/constexpr . Das geht nicht mit std::stringkönnen Sie auch hier nach String-Verkettungen suchen: stackoverflow.com/a/9054709/1938163
– Marco A.
16. Juli 2014 um 15:02 Uhr
@StevenLu: Ohne Compiler-Unterstützung können Sie keine sinnvolle Reflektion durchführen.
– Welpe
16. Juli 2014 um 15:05 Uhr
@Marco Super!!!! Vielen Dank für die Links. @Puppy Nun, ich bin noch nicht fertig, aber wenn ich dir die Beweise dafür zeigen kann, werde ich es tun. C++11 hat eine nette Trickkiste. Es kann ausreichend sein. (Tipp. Epische Mengen an Präprozessor-Makros und Templates)
Noch besser wäre es, das Bit zu vermeiden, in dem Sie einen ungültigen Zeiger (auf freigegebenen Speicher) zurückgeben.
– Mike Seymour
16. Juli 2014 um 14:32 Uhr
@MikeSeymour Guter Punkt. Es scheint, als würde man den Rückgabetyp auf setzen
char const*
ist einfach nicht praktikabel– Steven Lu
16. Juli 2014 um 14:46 Uhr
std::string
verwendet dynamischen Speicher, daher kann ich mir keinen Grund vorstellen, dies beim Kompilierungstyp zu tun, insbesondere nicht für die Leistung.– Neil Kirk
16. Juli 2014 um 16:50 Uhr
@NeilKirk der Punkt ist, dass ich es nicht verwenden muss
std::string
– Steven Lu
16. Juli 2014 um 17:39 Uhr
Einen echten C++-String-Typ zur Kompilierzeit zu haben, wäre ein großartiges Werkzeug, das man im Standard haben könnte, und es ist machbar, aber es ist noch nicht passiert. Diese neue Vorschlag ist aber interessant.
– hellseherisch
16. Juli 2014 um 22:09 Uhr