使用不同/未知类型的类模板初始化向量

时间:2016-12-20 15:34:19

标签: c++ class templates

为自己处理命令行解析器。我立刻就知道我的这个结构会遇到麻烦,并希望有人可以为解决方案提供建议。

我想将参数的参数列表(基于模板)存储在可能包含各种不同数据类型的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)
        {

        }
    };
}

1 个答案:

答案 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);