首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++模板过度使用

C++模板过度使用
EN

Stack Overflow用户
提问于 2017-01-13 15:06:05
回答 2查看 1.3K关注 0票数 3

我收集了两个模板专业化使用的代码摘录,这些代码摘录让我觉得特别奇怪。我甚至会说他们毫无必要的浮华。

总的来说,我怀疑模板实际上是设计这些对象的最佳方法(尤其是第一种情况)。

哪一种方法更好,为什么呢?还是有一种完全不同的方法更好?

1)用模板代替传递到函数的指针:

代码语言:javascript
复制
//fusion_manager.h
template <typename InputFilterAlgorithm,
          typename PredictionAlgorithm,
          typename AssociationAlgorithm,
          typename FusionAlgorithm>
class FusionManager
{
public:
    FusionManager(Environment& env);
    ...
private:
    Environment& env_m;
    InputFilterAlgorithm filter_alg_m;
    PredictionAlgorithm prediction_alg_m;
    AssociationAlgorithm association_alg_m;
    FusionAlgorithm fusion_alg_m;
    ...
};

//fusion_manager.cpp
template <typename InputFilterAlgorithm,
          typename PredictionAlgorithm,
          typename AssociationAlgorithm,
          typename FusionAlgorithm>
FusionManager<InputFilterAlgorithm,
              PredictionAlgorithm,
              AssociationAlgorithm,
              FusionAlgorithm,
              TrackExtendedDataType>::FusionManager(Environment& env)
        : 
          env_m(env),
          filter_alg_m(env),
          prediction_alg_m(env),
          association_alg_m(env),
          fusion_alg_m(env)
{
    ...
}

//main.cpp
...
FusionManager<TestInputFilterAlgorithm,
              TestPredictionAlgorithm,
              TestAssociationAlgorithm,
              TestFusionAlgorithm> fusionManager(env);
...

用于使用以下内容的...Instead:

代码语言:javascript
复制
//fusion_manager.h
class FusionManager
{
public:
  //Let's say each algorithm is encapsulated by a class
  FusionManager(Environment& env,
          InputFilterAlgorithm&&,
                 PredictionAlgorithm&&,
                 AssociationAlgorithm&&,
                 FusionAlgorithm&&);
private:
  Environment& env_m;
    InputFilterAlgorithm filter_alg_m;
    PredictionAlgorithm prediction_alg_m;
    AssociationAlgorithm association_alg_m;
    FusionAlgorithm fusion_alg_m;
};

//fusion_manager.cpp
FusionManager::FusionManager(Environment& env, 
                     InputFilterAlgorithm&& filter_alg,
                     PredictionAlgorithm&& prediction_alg,
                     AssociationAlgorithm&& association_alg,
                     FusionAlgorithm&& fusion_alg)
          :
              env_m(env),
              filter_alg_m(std::move(filter_alg)),
              prediction_alg_m(std::move(prediction_alg)),
              association_alg_m(std::move(association_alg)),
              fusion_alg_m(std::move(fusion_alg))
{
  ...
}

//main.cpp
...
FusionManager<TestInputFilterAlgorithm,
            TestPredictionAlgorithm,
            TestAssociationAlgorithm,
            TestFusionAlgorithm> fusionManager(env);
...

2)使用模板代替继承和虚拟方法:

代码语言:javascript
复制
//factorization.h
template<typename ProbabilityDistributionType>
class Factorization
{
...
public:
    ProbabilityDistributionType factorize();
private:
    std::Vector<ProbabilityDistributionType> factors_m;
...
};

//factorization.cpp
template<>
CPD Factorization<CPD>::factorize()
{
    for (auto & factor : factors_m)
    {
        factor.factorize();//This will call the factorize method of CPD
    }
}

template<>
JointProbDistr Factorization<JointProbDistr>::factorize()
{
    for (auto & factor : factors_m)
    {
        factor.factorize();//This will call the factorize method of JointProbDistr
    }
}

而不是使用这样的东西:

代码语言:javascript
复制
//factorization.h
template<typename ProbabilityDistributionType>
class Factorization
{
...
public:
    virtual ProbabilityDistributionType factorize() = 0;
private:
    std::Vector<ProbabilityDistributionType> factors_m;
...
};


//cpd_factorization.h
class CPDFactorization : public Factorization<CPD>
{
...
public:
    CPD factorize();//Implementing the parent's pure virtual method. This will call the factorize method of CPD
};

//jointprobdistr_factorization.h
class CPDFactorization : public Factorization<JointProbDistr>
{
...
public:
    JointProbDistr factorize();//Implementing the parent's pure virtual method. This will call the factorize method of JointProbDistr
};
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-13 15:28:10

使用模板具有编译器看到使用模板的完全专用实现的优点和缺点。

这是一个优势,因为它允许编译器更积极地进行优化:它可以随意内联,并解决函数调用之间的任何数据转移,从而删除程序员为以方便的方式构造源代码而引入的所有cruft。

这是一个缺点,因为它强制模板决策为编译时决策。如果变量是模板参数,则不能依赖运行时提供的输入。想象一下,如果std::string的长度是一个模板参数,那么会发生什么:字符串操作将与FORTRAN一样灵活。你绝对不想这样。当然,有些事情应该在编译时就知道,把它们作为模板参数是很好的。但是,如果过度使用模板,就会得到不必要的僵化代码。(去过那里,做了那件事,学会了避开它。)

这也是一个缺点,因为当模板的实现发生变化时,它会强制重新编译所有使用的模板。如果你的程序是除了main之外的所有模板,你必须重新编译每一个小的改变。如果使用指向函数、虚拟函数和/或函式的指针,则当调用函数的实现发生变化时,不需要重新编译调用站点。在正确设置的构建系统中,它们将依赖于报头,除非出现中断的接口更改,否则不会更改标头。对我来说,这样做的结果是,我的所有模板都应该是小的、自我包含的代码,这些代码不依赖于多个层中的其他模板。

总之,模板是一个很好的工具,同时也是一个非常容易过度使用的工具。当你没有得到任何真正的优势时,尽量不要使用它们。

票数 4
EN

Stack Overflow用户

发布于 2017-01-13 15:27:53

第一种方法可以与任何可调用的指针、std::function等一起使用。

你的建议在类型上非常有限.

第二种方法避免了虚拟调用,在您想要避免这种调用的情况下,虚拟调用非常有用,并且为内联提供了更多的机会。

简而言之:第一种方法使用模板来实现灵活性,第二种使用模板来实现性能。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41637587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档