【问题标题】:Choose variable type at runtime through config file通过配置文件在运行时选择变量类型
【发布时间】:2016-11-28 17:38:35
【问题描述】:

我已经看到了处理在运行时动态选择变量类型的答案(thisthis,以及从那里开始的链接),但是,即使有些可能有点超出我的头脑(相当C++ 新手),有没有办法从配置文件中读取变量类型并在运行时使用它?

比如config可能有type=double一行,可以通过程序的设置改成type=long double,不用重启应用就可以使用那个变量类型。


我需要计算一些多项式的根。有些,即使是小订单,也需要很大的精度,如果他们达到高订单,他们需要更大的精度。不过,对于足够小的数字,我可以取消 doublelong double,但随着我的数字越来越高,我需要 MPFRC++(这是我目前正在唱的)。我想避免减速(即使对于较小的订单来说并不那么明显),因为只有在需要时才能使用高精度。

【问题讨论】:

  • 简单回答:没有。
  • c++ 程序中使用的所有变量类型都是在编译时确定和实例化的。也许您可以链接其中一些答案,我们可以解释那里做了什么。
  • 也许你可以使用 if else like if(type=="double") double var;否则如果.....
  • @NathanOliver 那么不,谢谢你的回答。尽管我不认为反对票对 C++ 初学者是一种激励。对于知识渊博的人来说,答案可能很明显,但对我来说却不是。
  • @aconcernedcitizen 好的,假设您可以在运行时更改数据类型。您这样做到底想达到什么目的?

标签: c++ type-conversion runtime


【解决方案1】:

您可以使用Factory Pattern 以及Strategy Pattern 和适当的接口。类似的东西:

struct IPolyRootSolver {
    virtual PolyRoot calcRoot(const Polynom& poly) const = 0;
    virtual ~IPolyRootSolver () {}
};

class DoublePolyRootSolver : public IPolyRootSolver {
public:
    PolyRoot calcRoot(const Polynom& poly) {
        // Implementation based on double precision
    }
};

class LongDoublePolyRootSolver : public IPolyRootSolver {
public:
    PolyRoot calcRoot(const Polynom& poly) {
        // Implementation based on long double precision
    }
};

class MPFRCPolyRootSolver : public IPolyRootSolver {
public:
    PolyRoot calcRoot(const Polynom& poly) {
        // Implementation based on MPFRC++ precision
    }
};

class RootSolverFactory {
public:
    RootSolverFactory(const std::string configFile) {
         // Read config file and install a mechanism to watch for changes
    }

    std::unique_ptr<IPolyRootSolver> getConfiguredPolyRootSolver() {

         if(config file contains type = double) {
             return make_unique<IPolyRootSolver>(new DoublePolyRootSolver());
         }
         else if(config file contains type = long double) {
             return make_unique<IPolyRootSolver>(new LongDoublePolyRootSolver());
         }
         else if(config file contains type = MPFRC) {
             return make_unique<IPolyRootSolver>(new MPFRCPolyRootSolver ());
         }
         else {
             // Handle the default case
         }
};

我希望你明白我的意思。


如 cmets 中所述,您还可以使用命名空间中的独立函数,而不是上面提到的抽象接口解决方案:

namespace PolyRootDoublePrecision {
    PolyRoot calcRoot(const Polynom&);
}

namespace PolyRootLongDoublePrecision {
    PolyRoot calcRoot(const Polynom&);
}

namespace PolyRootMPFRCPrecision {
    PolyRoot calcRoot(const Polynom&);
}

class RootSolverFactory {
public:
    RootSolverFactory(const std::string configFile) {
         // Read config file and install a mechanism to watch for changes
    }

    std::function<PolyRoot (const Polynom&)> getConfiguredPolyRootSolver() {

         if(config file contains type = double) {
             return std::function<PolyRoot (const Polynom&)>
                         (PolyRootDoublePrecision::calcRoot);
         }
         else if(config file contains type = long double) {
             return std::function<PolyRoot (const Polynom&)>
                         (PolyRootLongDoublePrecision::calcRoot);
         }
         else if(config file contains type = MPFRC) {
             return std::function<PolyRoot (const Polynom&)>
                         (PolyRootMPFRCPrecision::calcRoot);
         }
         else {
             // Handle the default case
         }
};

除了使用配置文件之外,您还可以考虑从其他条件中选择要使用的策略作为配置文件。

例如对于您的情况,多项式表达式的复杂性(即子项的数量)似乎对于选择要使用的最佳策略起着至关重要的作用。所以你可以写一些类似的代码

    std::function<PolyRoot (const Polynom&)> getPolyRootSolver(const Polynom& polynom) {

         if(polynom.complexity() < 7) {
             return std::function<PolyRoot (const Polynom&)>
                         (PolyRootDoublePrecision::calcRoot);
         }
         else if(polynom.complexity() >= 7 &&
                 polynom.complexity() < 50) {
             return std::function<PolyRoot (const Polynom&)>
                         (PolyRootLongDoublePrecision::calcRoot);
         }
         else if(polynom.complexity() >= 50) {
             return std::function<PolyRoot (const Polynom&)>
                         (PolyRootMPFRCPrecision::calcRoot);
         }
};

【讨论】:

  • 我认为这可以很好地补充其他答案。我已经将根求解器作为命名空间,但它可以很容易地转换。只是,它相当大,并且可能会以代码大小为代价。我很抱歉我的问题含糊不清,但是,为了更清楚地了解范围,我想到的是linear.com/designtools/software/#LTspice。您可以添加.opt numdgt=7 并且任何&gt;=7 都将使用double 而不是float,所以我想知道配置是否不能这样做,因为我的程序仅用于多项式&co。
  • @aconcernedcitizen 另一种简化工厂(没有接口)的方法是使用std::function&lt;Poly (const Polynom&amp;)&gt; 作为getConfiguredPolyRootSolver() 函数的返回类型,如果您已经在命名空间中有独立的函数。跨度>
  • 这是一个很好的答案,对于初学者来说,它被证明是一个很好的起点,所以我将其标记为答案。
  • @aconcernedcitizen 我已经更新了我的答案,以便更多地了解broadness
  • 最后一部分看起来确实更合适。它仍然需要 3 倍的代码,但也许我可以通过不重用所有辅助函数来摆脱困境,只是也许。越看越觉得是最好的选择。我目前的方法涉及为 MPFRC++ 根查找传递可变精度,例如64+8*N,它因多项式的类型而异。但是根查找并不是我唯一要做的事情,这就是为什么我想尽可能多地使用原生格式。谢谢你的回答。
猜你喜欢
  • 2019-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-13
  • 2017-11-14
  • 1970-01-01
  • 2017-03-17
  • 1970-01-01
相关资源
最近更新 更多