C++ 结构模板特化

2023-12-20

我正在尝试开发自己的 3D 渲染器,为此我需要一个 3D 矢量结构。我试图使其尽可能通用,因此我使用模板化结构。

我创建了一个Vec<size_t, typename>为了简单起见,我将 Vec 专门化为具有 x 和 y 属性。像这样:

template <size_t DIM, typename T>
struct Vec
{
    T data[DIM];

    Vec() : data() {}

    Vec(std::vector<T> _data)
    {
        assert(_data.size() == DIM);
        for (int i = DIM; i--; data[i] = _data[i])
            ;
    }

    template <typename U>
    Vec(Vec<DIM, U> v)
    {
        for (int i = 0; i < DIM; i++)
            data[i] = (T)v[i];
    }

    T &operator[](size_t idx)
    {
        return data[idx];
    }
};

template <size_t LEN, size_t DIM, typename T>
Vec<LEN, T> embed(Vec<DIM, T> &v, T fill = 1)
{
    Vec<LEN, T> ret;
    for (size_t i = LEN; i--; ret[i] = (i < DIM ? v[i] : fill))
        ;
    return ret;
}

template <size_t LEN, size_t DIM, typename T>
Vec<LEN, T> proj(Vec<DIM, T> &v)
{
    Vec<LEN, T> ret;
    for (size_t i = LEN; i--; ret[i] = v[i])
        ;
    return ret;
}


template <typename T>
struct Vec<2, T>
{
    union
    {
        T data[2];
        struct
        {
            T x, y;
        };
    };
};

typedef Vec<2, int> Vec2i;
typedef Vec<2, float> Vec2f;
typedef Vec<2, double> Vec2d;

但是当我这样做时,我收到此错误:

...
/src/main.cpp:61:62: error: no matching function for call to ‘Vec<2, int>::Vec(Vec<2, double>)’
   61 |                 verts[i] = (Vec<2, int>)proj<2>(face.verts[i]);
      |                                                              ^
...
/include/geometry.h:52:8: note: candidate: ‘Vec<2, int>::Vec()’
   52 | struct Vec<2, T>
      |        ^~~~~~~~~
/include/geometry.h:52:8: note:   candidate expects 0 arguments, 1 provided
/include/geometry.h:52:8: note: candidate: ‘constexpr Vec<2, int>::Vec(const Vec<2, int>&)’
/include/geometry.h:52:8: note:   no known conversion for argument 1 from ‘Vec<2, double>’ to ‘const Vec<2, int>&’
/include/geometry.h:52:8: note: candidate: ‘constexpr Vec<2, int>::Vec(Vec<2, int>&&)’
/include/geometry.h:52:8: note:   no known conversion for argument 1 from ‘Vec<2, double>’ to ‘Vec<2, int>&&’
/include/geometry.h: In instantiation of ‘Vec<LEN, T> proj(Vec<DIM, T>&) [with long unsigned int LEN = 2; long unsigned int DIM = 3; T = double]’:
/src/main.cpp:61:62:   required from here
/include/geometry.h:46:34: error: no match for ‘operator[]’ (operand types are ‘Vec<2, double>’ and ‘size_t’ {aka ‘long unsigned int’})
   46 |     for (size_t i = LEN; i--; ret[i] = v[i])
      |                               ~~~^
...

Vec 没有继承函数?为什么我会收到这些错误?


班级专业化是一张白纸;您必须提供整个实现,这可能会造成大量重复。这似乎不太适合您提出的用例:根据维度添加便利访问器。

我建议使用一个模板类,其中包含根据维度有条件启用的访问器。这会给阅读类带来一些混乱,但不会出现代码重复。

另外,由于尺寸是模板参数,因此您可以使用std::array对于数据成员。

下面的代码演示了这些想法。它使用一些高级语言功能,因此您可能必须根据您使用的语言版本来调整实现细节。

示例代码

#include <array>
#include <iostream>
#include <vector>

using std::cin, std::cout, std::endl;


template<size_t D, class T>
struct Vec {
    Vec() : data_() { }

    template<class... Us> requires (sizeof...(Us) == D and (std::is_convertible_v<Us, T> and ...))
    Vec(Us... args)
        : data_({args...}) {
    }

    Vec(const std::vector<T>& other) {
        assert(other.size() == D);
        std::copy(other.begin(), other.end(), data_.begin());
    }

    template<class U>
    Vec(const Vec<D, U>& other) {
        std::copy(other.begin(), other.end(), data_.begin());
    }

    auto& operator[](size_t idx) { return data_[idx];  }
    const auto& operator[](size_t idx) const { return data_[idx]; }

    T& x() { return data_[0]; }
    const T& x() const { return data_[0]; }

    T& y() requires (D > 1) { return data_[1]; }
    const T& y() const requires (D > 1) { return data_[1];  }

    T& z() requires (D > 2) { return data_[2]; }
    const T& z() const requires (D > 2) { return data_[2]; }

    T& w() requires (D > 3) { return data_[3]; }
    const T& w() const requires (D > 3) { return data_[3]; }

private:
    std::array<T, D> data_;
};


int main(int argc, const char *argv[]) {
    Vec<1, int> a(1);
    cout << a.x() << endl;

    Vec<2, int> b(1, 2);
    cout << b.x() << " " << b.y() << endl;

    Vec<3, int> c(1, 2, 3);
    cout << c.x() << " " << c.y() << " " << c.z() << endl;

    Vec<4, int> d(1, 2, 3, 4);
    cout << d.x() << " " << d.y() << " " << d.z() << " " << d.w() << endl;
}

Output

1
1 2
1 2 3
1 2 3 4
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 结构模板特化 的相关文章

  • 在 CPP 类中将 C 函数声明为友元

    我需要在 C 函数中使用类的私有变量 我正在做这样的事情 class Helper private std string name public std getName return name friend extern C void in
  • Grpc - 将消息从一个客户端发送到连接到同一服务器的另一个客户端

    是否可以将消息从一个客户端发送到连接到同一服务器的另一个客户端 我想将数据从一个客户端发送到服务器然后发送到特定客户端 我想我需要获取客户端 ID 但我不知道如何获取此 ID 以及如何从服务器将此消息发送到该客户端 我这里有一个样本 这是一
  • 未找到 Boost 库,但编译正常

    我正在尝试在 C 中使用 boost 的文件系统 使用时看起来编译没问题 c c Analyse c o Analyse o g W Wall L usr local lib lboost filesystem lboost system
  • 如何将 SOLID 原则应用到现有项目中

    我对这个问题的主观性表示歉意 但我有点卡住了 我希望之前处理过这个问题的人能够提供一些指导和建议 我有 现在已经成为 一个用 C 2 0 编写的非常大的 RESTful API 项目 并且我的一些类已经变得巨大 我的主要 API 类就是一个
  • extern 声明和函数定义都在同一文件中

    我只是浏览了一下gcc源文件 在gcc c 我发现了类似的东西 extern int main int char int main int argc char argv 现在我的疑问是extern是告诉编译器特定的函数不在这个文件中 但可以
  • 处理右值时的 insert 与 emplace

    std string myString std unordered set
  • 如何在 C# Designer.cs 代码中使用常量字符串?

    如何在 designer cs 文件中引用常量字符串 一个直接的答案是在我的 cs 文件中创建一个私有字符串变量 然后编辑 Designer cs 文件以使用此变量 而不是对字符串进行硬编码 但设计者不喜欢这样抛出错误 我明白为什么这行不通
  • 如何使用 Regex.Replace 从字符串中删除数字?

    我需要使用Regex Replace从字符串中删除所有数字和符号 输入示例 123 abcd33输出示例 abcd 请尝试以下操作 var output Regex Replace input d string Empty The d标识符
  • 什么是空终止字符串?

    它与什么不同标准 字符串 http www cplusplus com reference string string 字符串 实际上只是一个数组chars 空终止字符串是指其中包含空字符的字符串 0 标记字符串的结尾 不一定是数组的结尾
  • 如何使用 ASP.NET Core 获取其他用户的声明

    我仍在学习 ASP NET Core 的身份 我正在进行基于声明的令牌授权 大多数示例都是关于 当前 登录用户的 就我而言 我的 RPC 服务正在接收身份数据库中某个用户的用户名和密码 我需要 验证是否存在具有此类凭据的用户 获取该用户的所
  • 获取没有显式特征的整数模板参数的有符号/无符号变体

    我希望定义一个模板类 其模板参数始终是整数类型 该类将包含两个成员 其中之一是类型T 另一个作为类型的无符号变体T 即如果T int then T Unsigned unsigned int 我的第一直觉是这样做 template
  • 在 C# 中检查 PowerShell 执行策略的最佳方法是什么?

    当你跑步时Get ExecutionPolicy在 PowerShell 中 它得到有效的执行政策 https learn microsoft com en us powershell module microsoft powershell
  • 如何使用 x64 运行 cl?

    我遇到了和这里同样的问题致命错误 C1034 windows h 未设置包含路径 https stackoverflow com questions 931652 fatal error c1034 windows h no include
  • 是否使用 C# 数据集? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我对 C 中的数据集概念有点困惑 编码 ASP NET 站点 但这并不重要 在我的阅读中 我了解到它们 本质上 用作我的应用程序和我的
  • 将二变量 std::function 转换为单变量 std::function

    我有一个函数 它获取两个值 x 和 y 并返回结果 std function lt double double double gt mult double x double y return x y 现在我想得到一个常量 y 的单变量函数
  • 如何在 C# 中创建异步方法?

    我读过的每一篇博客文章都会告诉您如何在 C 中使用异步方法 但由于某些奇怪的原因 从未解释如何构建您自己的异步方法来使用 所以我现在有这段代码使用我的方法 private async void button1 Click object se
  • 比较:接口方法、虚方法、抽象方法

    它们各自的优点和缺点是什么 接口方法 虚拟方法 抽象方法 什么时候应该选择什么 做出这一决定时应牢记哪些要点 虚拟和抽象几乎是一样的 虚方法在基类中有一个实现 可以选择重写 而抽象方法则没有 并且must在子类中被覆盖 否则它们是相同的 在
  • C++ 对象用 new 创建,用 free() 销毁;这有多糟糕?

    我正在修改一个相对较大的 C 程序 不幸的是 并不总是清楚我之前的人使用的是 C 还是 C 语法 这是在一所大学的电气工程系 我们 EE 总是想用 C 来做所有事情 不幸的是 在这种情况下 人们实际上可以逃脱惩罚 但是 如果有人创建一个对象
  • Visual Studio 2015:v120 与 v140?

    仅供参考 Win10 x64 我今天开始尝试 Visual Studio 2015 在弄清楚如何运行 C C 部分后 我尝试加载一个大型个人项目 该项目使用非官方的glsdk http glsdk sourceforge net docs
  • 如何解压 msgpack 文件?

    我正在将 msgpack 编码的数据写入文件 在编写时 我只是使用 C API 的 fbuffer 如 我为示例删除了所有错误处理 FILE fp fopen filename ab msgpack packer pk msgpack pa

随机推荐

  • Android 上的 ThreeTen-Backport 错误 - ZoneRulesException:未注册时区数据文件

    我正在为我的 Android 项目使用 ThreeTen Backport 库 因为 java time 尚未在 Android 开发中实现 当我写作时LocalDate today LocalDate now or LocalTime t
  • Elasticsearch 术语和总和聚合

    我在 elasticsearch 1 5 中有如下文档 gender name unknown value 12 name male value 89 name female value 84 并非所有文档都包含三个选项 男 女 未知 我想
  • 如何使用 Entity Framework CF 在父实体之前删除子实体?

    我正在尝试使用 EF 代码优先删除数据库记录 deleteMe 和它的孩子们 deleteMe Prices foreach var deleteMe in deleteThese Delete validation if CanDelet
  • 在构造函数中访问容器子部件尺寸

    假设我的班级有两个人Gtk Containers像这样 class Example public Gtk VBox public Example virtual Example private Gtk HBox m c1 First con
  • Node/Express:会话过期事件?

    在 ASP NET 上 我们有一个会话过期事件 我将 node js 与express js 以及会话的默认内存存储一起使用 每次我重新启动节点时 会话都会丢失 理想情况下 我想将会话保存到数据库 不能使用 redis 是否有会话过期事件
  • ASP.NET:隐藏gridview中的列

    有没有办法可以通过代码控制列 我有一个下拉框 其中选择 每日和周末 网格视图列包含星期一 星期二 星期三 星期四 星期五 星期六 星期日 如果用户选择 每日 我只想显示周一到周五的列 可以通过代码进行控制 哦 我在我的网页中使用这个 gri
  • 如何获取缓存图像 SDWebImage 的数据

    我正在使用 SDWebImage 库在 UICollectionView 中缓存 Web 图像 cell packItemImage sd setImage with URL string smileImageUrl indexPath r
  • Meteor JS:如何为多个选择器创建事件处理程序?

    我试图为多个元素创建相同的事件处理程序 但在文档中找不到执行此操作的任何位置 在下面的示例中 我尝试为所有文本处理创建一个单击处理程序 这适用于h1 但不适用于其余的 Template page events click h1 h2 h3
  • 从正在运行的进程中分离

    我面临着一个有趣的情况 我正在开发一个手电筒 https github com w0lfschild Flashlight插件在将来的某个时刻触发警报 问题是 手电筒会在 30 秒后杀死脚本 因此 我既不能等待足够长的时间来激活闹钟 也不能
  • 休眠 ID 生成器

    有人知道一些关于如何为 hibernate 创建自定义 ID 生成器的好教程吗 在 Google 上粗略搜索 hibernate 自定义 id 生成器教程 发现了以下可能性 我排除了那些看起来没有用的内容 并总结了每个内容的内容 http
  • 将标签添加到反应选择

    I am new to the react js here what I am trying to do is that 现在我尝试过的是 const options value chocolate label Chocolate valu
  • 我正在尝试使用 Stripe 和 NextJS 13.2.3 设置 webhook

    我能够通过内置 Stripe 页面成功结帐我的购物车 并且我会被重定向到我的 successUrl 路线 我的本地测试 webhook 正在按预期被调用 但是 当我包含代码来验证请求是否来自 Stripe 时 我收到一些错误 这是我在 Ne
  • COLLADA:反向绑定姿势在错误的空间?

    我正在编写自己的 COLLADA 导入器 我已经走了很远 加载了网格和材料等 但我在动画方面遇到了障碍 特别是 关节旋转 我用于对网格体进行蒙皮的公式很简单 weighted for i 0 i lt joint influences i
  • iPhone 的 /Documents 目录更改的通知

    我们有一个使用文件共享的应用程序 UIFileSharingEnable 已设置等 一切似乎都工作正常 但我正在寻找某种通知 说明何时在 iPhone 端添加 删除文件 有人可以建议吗 提前干杯 这个线程 https devforums a
  • len() 函数的成本

    费用是多少len https docs python org 2 library functions html lenPython 内置函数 列表 元组 字符串 字典 It s O 1 恒定时间 不取决于元素的实际长度 非常快 您提到的每种
  • 如何在 Firebase 托管上设置私有环境变量?

    由于 Divshot 最近关闭 我已将许多应用程序切换到 Firebase 托管 其中一些应用程序连接到外部 API 因此我需要一种在 Firebase 托管上存储私有环境变量 例如 用于 S3 访问的密钥 的方法 有人有什么想法吗 有这样
  • 如何从命令行调用多个文件到您的应用程序中?

    我正在向 Windows 注册表添加一个上下文菜单项 这样当我单击一个文件时 我可以调用我的应用程序 并将该文件作为参数设置到我的应用程序中 但是我如何才能将多个文件发送到我的应用程序 我选择的所有文件 现在我的命令是 C test dll
  • 解决方案无法在 Visual Studio 中运行/构建/重建

    当尝试在 Visual Studio 中对解决方案运行 生成 重建 时 没有任何反应 我可以使用 MSbuild exe 从命令提示符运行构建 这给了我期望的输出 构建成功 但是当尝试从 Visual Studio 运行它时 没有任何反应
  • geom_boxplot:将 alpha 水平映射到晶须和异常值

    有没有办法制作geom boxplot线条 胡须和离群点继承相同的alpha分配给箱线图fill在下面的情节中 library ggplot2 ggplot iris aes x Species y Sepal Length alpha S
  • C++ 结构模板特化

    我正在尝试开发自己的 3D 渲染器 为此我需要一个 3D 矢量结构 我试图使其尽可能通用 因此我使用模板化结构 我创建了一个Vec