C++ C++;模板过度使用

C++ C++;模板过度使用,c++,templates,C++,Templates,我收集了两个模板专业化使用的代码摘录,我发现它们特别奇怪。我甚至会称它们为不必要的浮华 一般来说,我怀疑模板是否是设计这些对象的最佳方式(尤其是第一种情况) 哪种方法更好?为什么?还是有一种完全不同的方法更好 1)用模板代替向函数传递指针: //fusion_manager.h template <typename InputFilterAlgorithm, typename PredictionAlgorithm, typename Associa

我收集了两个模板专业化使用的代码摘录,我发现它们特别奇怪。我甚至会称它们为不必要的浮华

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

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

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);
...
//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
    }
}
//fusion\u manager.h
模板
类融合管理器
{
公众:
FusionManager(环境和环境);
...
私人:
环境与环境;
输入过滤器算法过滤器;
预测算法预测算法;
联合算法联合算法;
融合算法融合算法;
...
};
//fusion_manager.cpp
模板
FusionManager::FusionManager(环境和环境)
: 
环境(环境),,
过滤器(环境),
预测(环境),
环保协会,
熔合分析(环境)
{
...
}
//main.cpp
...
FusionManager FusionManager(环境);
...
…而不是使用这样的东西:

//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);
...
//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
};
//fusion\u manager.h
类融合管理器
{
公众:
  //假设每个算法都由一个类封装
  FusionManager(环境和环境),
          InputFilterAlgorithm&,
                 预测算法&,
                 联想算法&&,
                 融合算法&);
私人:
  环境与环境;
    输入过滤器算法过滤器;
    预测算法预测算法;
    联合算法联合算法;
    融合算法融合算法;
};
//fusion_manager.cpp
FusionManager::FusionManager(环境和环境),
                     输入过滤算法和过滤算法,
                     预测算法与预测算法,
                     关联算法和关联算法,
                     融合算法和融合算法(alg)
          :
              环境(环境),,
              过滤器alg(标准::移动(过滤器alg)),
              预测值(标准::移动(预测值)),
              关联法(std::move(关联法)),
              fusion_alg_m(标准::移动(fusion_alg))
{
  ...
}
//main.cpp
...
FusionManager FusionManager(环境);
...
2)使用模板替代继承和虚拟方法:

//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);
...
//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
    }
}
//因式分解.h
模板
类因子分解
{
...
公众:
概率DistributionType factorize();
私人:
std::向量因子μm;
...
};
//因式分解
模板
CPD Factorization::factorize()
{
用于(自动和系数:系数)
{
factor.factorize();//这将调用CPD的factorize方法
}
}
模板
JointProbDisr分解::分解()
{
用于(自动和系数:系数)
{
factor.factorize();//这将调用JointProbDistrir的factorize方法
}
}
而不是像这样使用:

//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);
...
//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
};
//因式分解.h
模板
类因子分解
{
...
公众:
虚拟概率DistributionType factorize()=0;
私人:
std::向量因子μm;
...
};
//cpd_因式分解
类CPDFactorization:公共因子分解
{
...
公众:
CPD factorize();//实现父级的纯虚拟方法。这将调用CPD的factorize方法
};
//jointProbDistrir\u因式分解.h
类CPDFactorization:公共因子分解
{
...
公众:
JointProbDisr factorize();//实现父级的纯虚拟方法。这将调用JointProbDisr的factorize方法
};

第一个函数可以与任何可调用的函数指针、
std::function
等一起使用。
你的建议很有限

第二种方法避免虚拟调用,这在希望避免虚拟调用的情况下非常有用,并提供了更多的内联机会


简而言之:第一种使用模板是为了灵活性,第二种使用模板是为了性能。

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

这是一个优势,因为它允许编译器更积极地进行优化:它可以根据需要进行内联,并解决函数调用之间的任何数据转换,消除程序员为了方便地构造源代码而可能引入的所有障碍

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

这也是一个缺点,因为当模板的实现发生变化时,它会强制重新编译模板的所有用途。如果您的程序是除main之外的所有模板,那么您必须为每一个小更改重新编译所有内容。如果使用指向函数、虚拟函数和/或函子的指针,则在被调用函数的实现发生更改时,不需要重新编译调用站点。在正确设置的构建系统中,它们将取决于标头