为自己处理命令行解析器。我立刻就知道我的这个结构会遇到麻烦,并希望有人可以为解决方案提供建议。
我想将参数的参数列表(基于模板)存储在可能包含各种不同数据类型的vector
中。但根据我的理解,你必须静态定义vector<template<type>>
。有没有办法除了多种类型?
这是我的意思的一个例子:
#include <vector>
#include <memory>
namespace clparser
{
class CommandLine {
private:
std::vector<Parameter<AnyType??>*> ArgumentList;
public:
void Add(Parameter<AnyType??>* Parameter) { ArgumentList.push_back(Parameter); }
};
template<typename T>
class Parameter {
private:
const char *ShortOption;
const char *LongOption;
const char *Description;
const bool RequiredField;
const char *DefaultValue;
public:
Parameter(const char *ShortOption, const char *LongOption, const char *Description, const bool RequiredField, const char *DefaultValue)
: ShortOption(ShortOption), LongOption(LongOption), Description(Description), RequiredField(RequiredField), DefaultValue(DefaultValue)
{
}
};
}
答案 0 :(得分:0)
如果您可以接受C ++ 11解决方案,我建议您使用命令行解析器中的iper-simplified版本。希望这对你有所启发。
我的解决方案背后的想法是使用基本/派生多态:纯虚拟class optBase
,它是一组专用于选项的模板类的基础(在以下示例中,仅class opt
;但我的解析器还有其他三个。)
然后(不是模板)class yData
包含std::unique_ptr<optBase>
(如果你使用一个指向optBase
的简单指针,你也可以在C ++ 98中编译,我想;但我建议使用C ++ 11或更新版本。
class yData
(粗略地)对应你的class Parameter
但是(这是诀窍)不是模板类;包含指向模板类的基指针。
我的class yarg
对应于您的class clparser
,而我的std::map<int, yData> idMap
对应(大致)与std::vector<Parameter<AnyType??>*> ArgumentList
对应。
要提供idMap
,我已经开发了一套模板方法(每个派生自optbase
类一个);在下面的示例中,您可以看到其中一个的超级简化版本:addOpt()
(大致对应于您的Add()
)。
在以下示例中,您可以看到main()
有一些addOpt()
用于int
:第一个用于double
参数,第二个用于#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, "!!");
}
参数(重要(以及我解决方案的弱点):返回值必须保存在引用变量中,而不是保存在简单变量中。
System.Error(reInvalidPtr);