C++11 C++;元组与可读性

C++11 C++;元组与可读性,c++11,tuples,gaussian,C++11,Tuples,Gaussian,我认为这更像是一个关于C++11中可读性和元组类型的哲学问题 我正在编写一些代码来生成高斯混合模型(细节有点不相关,但它提供了一个很好的示例)。我的代码如下: GMM.hpp #pragma一次 #包括 #包括 #包括 #包括“./Util/Types.hpp” 名称空间LocalDescriptorAndBagoFeature { //加权高斯定义为(权重、平均向量、协方差矩阵) typedef std::tuple WeightedGaussian; 类GMM { 公众: GMM(国际

我认为这更像是一个关于C++11中可读性和元组类型的哲学问题

我正在编写一些代码来生成高斯混合模型(细节有点不相关,但它提供了一个很好的示例)。我的代码如下:

GMM.hpp
#pragma一次
#包括
#包括
#包括
#包括“./Util/Types.hpp”
名称空间LocalDescriptorAndBagoFeature
{   
//加权高斯定义为(权重、平均向量、协方差矩阵)
typedef std::tuple WeightedGaussian;
类GMM
{
公众:
GMM(国际努姆高斯人);
无效列车(常数特征集和特征集);
标准::向量超向量(常数Bagofferties和bof);
国际货币(无效)常量;
双运算符()(const cv::Mat&x)const;
私人:
静态双计算加权高斯分布(常数cv::Mat&x,加权高斯分布wg);
std::向量_高斯;
国际努姆高斯人;
};
}
GMM.cpp
使用名称空间localdescriptor和bagoffeature;
双GMM::ComputeWeightedGaussian(常数cv::Mat&x,WeightedGaussian wg)
{
双倍重量;
平均值,协方差;
标准::tie(重量、平均值、协方差)=wg;
cv::Mat精度;
cv::反转(协方差、精度);
双detp=cv::行列式(精度);
双输出=标准::sqrt(detp/2.0*M_-PI);
cv::Mat Meansdist=x-平均值;
cv::Mat MeansitTrans;
cv::转置(meanDist,meanDistTrans);
cv::Mat symmetricProduct=MeandDistTrans*精度*MeandDist;//这是一个“1x1”矩阵,例如标量值
双内=对称积在(0,0)/-2.0;
返回重量*外部*标准::外部(内部);
}
双GMM::operator()(const cv::Mat&x)const
{
return std::accumulate(_Gaussians.begin(),_Gaussians.end(),0,[&x](双val,WeightedGaussian wg){return val+ComputeWeightedGaussian(x,wg);});
}

在这种情况下,通过对加权高斯分布使用元组表示,而不是使用结构,甚至是使用具有自己运算符()的类,我是否获得了任何东西(清晰度、可读性、速度等等)

您正在稍微减少源代码的大小,但我认为您正在降低其总体可读性和类型安全性。具体而言,如果您定义:

struct WeightedGaussian{
双倍重量;
平均值,协方差;
};
那么你就没有机会写不正确的东西了

std::tie(重量、协方差、平均值)=wg;

并且您可以保证您的用户将使用
wg.mean
而不是
std::get(wg)
。最大的缺点是<代码> STD::tuple < /Calp>附带了“代码>操作程序的定义,谢谢您的回复,您是否会认为这是对tuple类型的滥用/滥用?基本上,作为程序员,我的直觉是“嘿,你在做一些奇怪的事情”,但如果我要写一些关于这个主题的数学,我可能会把高斯函数表示为
(w,u,C)
例如,我目前在codeOne中遇到的元组我对数学论文的投诉是,它们过度使用单字母变量名和未键入的元组,甚至键入不一致的元组也就是说,我不认为你的问题是元组的可怕用法。它确实保存了一些字符和
操作符中的潜在错误。这不是我想写或喜欢读的代码。
#pragma once
#include <opencv2/opencv.hpp>
#include <vector>
#include <tuple>
#include "../Util/Types.hpp"

namespace LocalDescriptorAndBagOfFeature 
{   
    // Weighted gaussian is defined as a (weight, mean vector, covariance matrix)
    typedef std::tuple<double, cv::Mat, cv::Mat> WeightedGaussian; 

    class GMM
    {
        public:
            GMM(int numGaussians);

            void Train(const FeatureSet &featureSet);
            std::vector<double> Supervector(const BagOfFeatures &bof);

            int NumGaussians(void) const;

            double operator ()(const cv::Mat &x) const;

        private:                        
            static double ComputeWeightedGaussian(const cv::Mat &x, WeightedGaussian wg);

            std::vector<WeightedGaussian> _Gaussians;

            int _NumGaussians;
    };
}
using namespace LocalDescriptorAndBagOfFeature;

double GMM::ComputeWeightedGaussian(const cv::Mat &x, WeightedGaussian wg)
{
    double weight;
    cv::Mat mean, covariance;
    std::tie(weight, mean, covariance) = wg;

    cv::Mat precision;
    cv::invert(covariance, precision);

    double detp = cv::determinant(precision);

    double outter = std::sqrt(detp / 2.0 * M_PI);

    cv::Mat meanDist = x - mean;
    cv::Mat meanDistTrans;
    cv::transpose(meanDist, meanDistTrans);

    cv::Mat symmetricProduct = meanDistTrans * precision * meanDist; // This is a "1x1" matrix e.g. a scalar value
    double inner = symmetricProduct.at<double>(0,0) / -2.0;

    return weight * outter * std::exp(inner);
}

double GMM::operator ()(const cv::Mat &x) const
{
    return std::accumulate(_Gaussians.begin(), _Gaussians.end(), 0, [&x](double val, WeightedGaussian wg) { return val + ComputeWeightedGaussian(x, wg); });
}