Wenn Sie eine C++ 11-Lösung akzeptieren kann, schlage ich vor, Sie eine iper vereinfachte Version von meinem Befehlszeilenparser. Hoffe, dass das für dich Inspiration sein kann.
Die Idee hinter meiner Lösung ist die Verwendung von Base/abgeleitet Polymorphismus: ein rein virtuellen class optBase
, die eine Basis für eine Reihe von Template-Klassen Optionen gewidmet ist (im folgende Beispiel nur class opt
, aber es gibt auch andere drei in mein Parser).
Dann wird die (nicht Vorlage) class yData
enthält ein std::unique_ptr<optBase>
(wenn Sie einen einfachen Zeiger auf optBase
verwenden, können Sie kompilieren in C++ 98 zu, nehme ich an, aber ich schlage vor, die Verwendung von C++ 11 oder höher).
class yData
entsprechen (grob) zu Ihrem tou Ihre class Parameter
aber (hier ist der Trick) ist keine Vorlagenklasse; einen Basiszeiger auf eine Vorlagenklasse enthalten.
Meine class yarg
entsprechen Ihrer class clparser
und meine std::map<int, yData> idMap
entsprechen (grob) Ihrer std::vector<Parameter<AnyType??>*> ArgumentList
.
Um idMap
zu füttern, habe ich eine Reihe von Vorlage-Methode entwickelt (eine für jede abgeleitete von optbase
Klassen); Im folgenden Beispiel sehen Sie eine iper-vereinfachte Version von einem von ihnen: addOpt()
(entspricht in etwa Ihrer Add()
).
Im folgenden Beispiel Sie ein wenig main()
mit ein paar Anwendungen für addOpt()
sehen: der erste für einen int
Parameter und die zweite für einen double
Parameter (wichtig (und Schwachpunkt meiner Lösung): Der Rückgabewert muss in einer Referenz Variable gespeichert werden, nicht in einer einfachen Variablen).
#include <map>
#include <memory>
class optBase
{
public:
// some pure virtual methods
};
template <typename X>
class opt : public optBase
{
private:
X val { };
// ...
public:
opt()
{ }
opt (X const & v0)
: val { v0 } // ...
{ }
X const & getVal() const
{ return val; }
X & getVal()
{ return val; }
// ...
};
// other optBase derived classes (for flags, containers of values, etc)
class yData
{
private:
// ...
std::unique_ptr<optBase> optB;
public:
yData (/* other arguments */ std::unique_ptr<optBase> optB0)
: /* something else */ optB { std::move(optB0) }
{ }
// ...
std::unique_ptr<optBase> const & getPnt() const
{ return optB; }
};
class yarg
{
private:
// ...
std::map<int, yData> idMap;
// ...
public:
// ...
template <typename T>
T & addOpt (/* other arguments */ T const & def = T())
{
int id { /* some value */ };
opt<T> * optP { nullptr };
// ...&
idMap.emplace(std::piecewise_construct,
std::forward_as_tuple(id),
std::forward_as_tuple(/* other arguments */
std::unique_ptr<optBase>(optP = new opt<T>(def))));
return optP->getVal();
}
};
int main()
{
yarg y;
// important: use a *reference*
auto & pi = y.addOpt(3); // pi is a int
auto & pd = y.addOpt(3.0); // pd is a double
static_assert(std::is_same<decltype(pi), int &>::value, "!");
static_assert(std::is_same<decltype(pd), double &>::value, "!!");
}
Vielleicht 'boost :: any'? –
Ich würde lieber keine Boost-Abhängigkeiten haben, aber wenn ich das mit der STL nicht schaffen kann ... Danke, – user0000001
Da C++ 17 'any' auch in' std' verfügbar sein wird –