不同的模板类实现,但成员函数相同

如何解决不同的模板类实现,但成员函数相同

我有一个模板矩阵类,其中包含一些典型的成员函数,例如def returnCode = mockRequest.getRequest().getParameter("returnCode") if( returnCode.equals("429")) { return "Response 429" } else if( returnCode.equals("500")) { return "Response 500" } else { return "Response 200" } inversedeterminant等。并且我想在模板中为这些成员函数重用代码固定-和动态大小矩阵的实现。 这可能吗?如果可以,怎么办?

在下面的代码中,像Eigen一样,我将“ operator*”用于动态尺寸。是的,我知道我可以为此使用一个库,但是对于我的应用程序,那是不可行的。 由于应用程序(CUDA)的性质,无法使用标准功能

是否可以根据模板参数使模板类具有不同的成员变量大小?例如,当-1Dynamic_Rows = -1时,数据仅为{ {1}},否则为Dynamic_Cols = -1

到目前为止,我有一个用于动态尺寸矩阵的模板类(以下示例为“ minimum ”,请注意,该代码容易出错/出错,因为我在“高级”类中相对较新)模板)。

但是在固定大小的矩阵实例化的情况下,我希望有一个固定大小的数据成员变量。

T **data

例如,下面的T data[Rows][Cols]函数的代码为

template<class T,int Dynamic_Rows,int Dynamic_Cols>
class CMatrix<T,-1,-1>
{
private:
   size_t n_rows,n_cols;
   T** data;

   void allocate_data();
   void deallocate_data();

public:
   CMatrix(const size_t n_rows,const size_t n_cols);
   CMatrix(const CMatrix& other);
   ~CMatrix();
   CMatrix& operator=(const CMatrix& rhs);
   CMatrix exp() const;
};

我现在唯一想到的允许同时使用动态和固定大小矩阵的方法是基本上将类的另一个模板实现为

exp()

使用可变参数模板

template <class T,int Dynamic_Cols>
CMatrix<T,-1> CMatrix<T,-1>::exp() const
{
   CMatrix<T,-1> result(n_rows,n_cols);
   for (size_t i = 0; i < n_rows; i++)
   {
      for (size_t j = 0; j < n_cols; j++)
      {
         result.data[i][j] = exp(result.data[i][j]);
      }
   }
   return result;
}

但是那只会复制我大多数成员函数的代码!

解决方法

这是使用CRTP进行此类专业化的一种非常通用的方法。并不需要有一个简单的单一条件即可用于选择数据成员的实现,而其余条件保持不变。

template <class T,class Impl> class MatrixBase {

   // data is NOT defined here
   Impl exp() const
   {
        Impl& self = static_cast<Impl&>(*this);             // <-- this is magic
        Impl result = self;                                 // <-- this is magic
        for (size_t i = 0; i < n_rows; i++)
        {
            for (size_t j = 0; j < n_cols; j++)
            {
                result.data[i][j] = exp(result.data[i][j]); // <-- data is defined in Impl
            }
        }
        return result;
    }
    // other functions that do not depend on actual type of data
};

template <class T>
class DynamicMatrix : public MatrixBase<T,DynamicMatrix<T>> {
    T** data;
    // define constructors etc here
};

template <class T,int Rows,int Cols>
class StaticMatrix : public MatrixBase<T,StaticMatrix<T,Rows,Cols>> {
    T[Rows][Cols] data;
    // define constructors etc here
};

现在您同时拥有StaticMatrixDynamicMatrix,可以根据需要将它们统一为一个别名模板。

template <class T,int Cols>
using CMatrix = std::conditional_t <(Rows >= 0 && Cols >= 0),Cols>,DynamicMatrix<T>
                                   >;
,

是否可能.... [...] ...当Dynamic_Rows = -1Dynamic_Cols = -1时,数据仅为T **data,否则为T data[Rows][Cols]

您可以提供特征类型,其特征可以为CMatrix提供适当的类型

template<typename T,int Cols> struct type_helper final {
    static_assert(Rows >= 0 && Cols >= 0,"Rows and COls must be valid!");
    using type = T[Rows][Cols];
};

template<typename T> struct type_helper<T,-1,-1>  final {
    using type = T**;
};

现在上课了

template<class T,int Dynamic_Rows = -1,int Dynamic_Cols = -1>
class CMatrix /* final */
{
    // get the member Type like this!
    using Type = typename type_helper<T,Dynamic_Rows,Dynamic_Cols>::type;

    Type data;
public:

};

See a demo online

,

您可以使用std::conditional_t根据一些编译时常量选择一种或另一种类型,而无需复制类。

但是-我曾经做过非常类似的事情,发现使用固定大小的数据结构(std::array而不是std::vector)在实际使用案例中几乎没有改善。 固定大小的数组(std::arraytype[fixed_size])的一个很大的优点是编译器能够优化很多操作,但是如果数组很大,则好处可以忽略不计。

此外,您应该考虑 n。 “代词” m。的注释-特别是如果您使用的是GPU(它们往往需要内存中连续的数据结构)。代替使用T** data,在每个维度上使用单个std::vector<T>,并使用附加的std::array<size_t,number_of_dimensions>。然后,您可以使用以下方式转换索引:

using Indices = std::array<size_t,number_of_dimensions>;

template <unsigned int n = number_of_dimensions>
static inline size_t indices_to_offset(Indices const & indices,Indices const & dimensions){
    if constexpr (n == 0) return 0;
    else {
        size_t const next_index_number = indices[n-1];
        assert(next_index_number < dimensions[n-1]);
        return next_index_number +
            dimensions[n-1]*indices_to_offset<n-1>(indices,dimensions);
    }
}

template <unsigned int n = number_of_dimensions>
static inline Indices offset_to_indices(size_t const offset,Indices const & dimensions,Indices indices = Indices()){
    if constexpr (n == 0) return indices;
    else {
        size_t const fast_dimension_size = dimensions[n-1];
        indices[n-1] = offset % fast_dimension_size;
        return offset_to_indices<n-1>(offset/fast_dimension_size,dimensions,indices);
    }
}
,

将我的评论变成答案(使用rectangle代替Vector):

拆分您的课程,因此您有一部分专门研究特定的课程,而共有部分则是类似的:

Matrix

然后是公共部分:

// helper to allow variadic constructor without pitfall.
constexpr struct in_place_t{} in_place{};

template <typename T,std::size_t DIM>
class VectorData
{
protected: // You might even make it private and give the common accessor in public part
           // To avoid to use interface not shared with std::vector
    std::array<T,DIM> data;
public:
    VectorData() = default;

    template <typename ... Ts>
    VectorData(in_place_t,Ts&&... args) : data{std::forward<Ts>(args)...} {}
};

template <typename T>
class VectorData<T,std::size_t(-1)>
{
protected: // You might even make it private and give the common accessor in public part
           // To avoid to use interface not shared with std::array
    std::vector<T> data;
public:
    explicit VectorData(std::size_t size) : data(size) {}

    template <typename ... Ts>
    VectorData(in_place_t,Ts&&... args) : data{std::forward<Ts>(args)...} {}
};

Demo

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-