gpt4 book ai didi

C++ 模板过度使用

转载 作者:太空狗 更新时间:2023-10-29 20:10:08 25 4
gpt4 key购买 nike

我将我遇到的模板特化使用的两个代码摘录放在一起,我觉得它们特别奇怪。我什至会称他们为不必要的华而不实。

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

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

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

//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);
...

...而不是使用这样的东西:

//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) 使用模板替代继承和虚方法:

//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
}
}

而不是使用这样的东西:

//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
};

最佳答案

使用模板既有优点也有缺点,因为编译器会看到使用模板的完全专用实现。

这是一个优势,因为它允许编译器更积极地进行优化:它可以尽可能多地内联,并解决函数调用之间的任何数据移动,消除程序员可能引入的所有问题努力以方便的方式构建他们的源代码。

这是一个缺点,因为它迫使模板化决策成为编译时决策。如果变量是模板参数,则它不能依赖于运行时给定的输入。想象一下,如果 std::string 的长度是一个模板参数会发生什么:字符串操作将像在 FORTRAN 中一样灵活。你绝对不想要这个。当然,有些东西在编译时就应该知道,将它们作为模板参数是非常可以的。但是,如果过度使用模板,就会得到不必要的死板代码。 (去过那里,做过那个,学会了避免它。)

这也是一个缺点,因为当模板的实现发生变化时,它会强制重新编译模板的所有使用。如果您的程序除了 main 之外都是模板,您必须为每个小的更改重新编译所有内容。如果您使用指向函数、虚函数和/或仿函数的指针,则当被调用函数的实现发生变化时,调用站点不需要重新编译。在正确设置的构建系统中,它们将取决于 header ,除非有中断的接口(interface)更改,否则 header 不会更改。对我来说,这样做的结果是,我的所有模板都应该是小的、独立的代码片段,不依赖于多层中的其他模板。

总而言之,模板是一个很棒的工具,同时也是一个很容易被过度使用的工具。当您没有从中获得任何真正的好处时,尽量不要使用它们。

关于C++ 模板过度使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41637587/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com