tl; dr: Gibt es eine Möglichkeit, ein Standardargument aus dem aktuellen Bereich zu allen impliziten Konstruktoren in C++ hinzuzufügen?Implizites Argument für Konvertierungskonstruktoren
Ich entwickle derzeit eine Schnittstelle für eine eingebettete Sprache in C++. Ziel ist es, syntaktisch korrekte Ausdrücke typsicher und komfortabel zu erstellen. Gerade jetzt, denke ich, dass das Erlernen einer schwergewichtigen Implementierung wie boost :: proto eine zu große Latenz in die Entwicklung bringen wird, also versuche ich meine eigene Implementierung zu rollen.
Hier ist eine kleine Demo:
#include <iostream>
#include <string>
#include <sstream>
class ExprBuilder
{
public:
ExprBuilder(const int val) : val(std::to_string(val)) {}
ExprBuilder(const std::string val) : val(val) {}
ExprBuilder(const char* val) : val(val) {}
ExprBuilder(const ExprBuilder& lhs, const ExprBuilder& arg) {
std::stringstream ss;
ss << "(" << lhs.val << " " << arg.val << ")";
val = ss.str();
}
const ExprBuilder operator()(const ExprBuilder& l) const {
return ExprBuilder(*this, l);
}
template<typename... Args>
const ExprBuilder operator()(const ExprBuilder& arg, Args... args) const
{
return (*this)(arg)(args...) ;
}
std::string val;
};
std::ostream& operator<<(std::ostream& os, const ExprBuilder& e)
{
os << e.val;
return os;
}
int main() {
ExprBuilder f("f");
std::cout << f(23, "foo", "baz") << std::endl;
}
Wie Sie sehen können, ist es ziemlich einfach Ausdrücke embedd aufgrund von C++ Überlastung und implizite Konvertierungen.
Ich stehe jedoch vor einem praktischen Problem: Im obigen Beispiel wurden alle Daten in Form von std :: string-Objekten zugewiesen. In der Praxis brauche ich etwas Komplexeres (AST-Knoten), die auf dem Heap zugewiesen und von einem dedizierten Besitzer verwaltet werden (Legacy-Code, kann nicht geändert werden). Also muss ich ein eindeutiges Argument übergeben (besagter Eigentümer) und es für die Zuweisungen verwenden. Ich würde hier lieber kein statisches Feld verwenden.
Was ich suche ist eine Möglichkeit zu verwenden fragen Sie den Benutzer, einen solchen Besitzer jedes Mal, wenn der Builder verwendet wird, aber auf eine bequeme Weise zu stellen. So etwas wie eine dynamisch begrenzte Variable wäre großartig. Gibt es eine Möglichkeit, in C++ folgendes zu erhalten:
class ExprBuilder
{
...
ExprBuilder(const ExprBuilder& lhs, const ExprBuilder& arg) {
return ExprBuilder(owner.allocate(lhs, rhs)); // use the owner implicitly
}
...
};
int main() {
Owner owner; // used in all ExprBuilder instances in the current scope
ExprBuilder f("f");
std::cout << f(23, "foo", "baz") << std::endl;
}
Ist das möglich?
bearbeiten: Ich möchte klarstellen, warum ich (bis jetzt) nicht eine globale Variable betrachte. Der Besitzer muss irgendwann vom Benutzer des Builders manuell freigegeben werden. Daher kann ich keine Ad-hoc-Datei erstellen. Daher kann der Benutzer den Besitzer insgesamt "vergessen". Um dies zu vermeiden, suche ich einen Weg, die Anwesenheit des Besitzers durch den Typchecker zu erzwingen.
denke ich, was Sie sagen, eine Art 'global variable' ist –
Sie eine statische/globale Variable mit' Owner' Raii gesetzt, und verwenden, die globale Variable in 'ExprBuilder'. – Jarod42
Sie meinen ein unique_ptr als globale Variable, um sicherzustellen, dass es nur im Kontext verwendet wird und explizit beibehalten werden muss? Würde dies nicht zu Laufzeitfehlern führen, wenn der Zeiger vom Benutzer vergessen wird? – choeger