c++ - 如何在模板与联合之间进行继承?
问题描述
我有以下两个对象。我想知道是否有一种方法可以Pixel
作为基类,PixelBGR
以便可以使用任何运算符(+、-、*、/、[] 等)而无需重新定义它们?
template<class T, std::size_t N>
struct Pixel
{
T ch[N];
inline T& operator[](const int x)
{
return ch[x];
}
};
template<class T>
struct PixelBGR
{
union
{
struct
{
T b;
T g;
T r;
};
T ch[3];
};
inline T& operator[](const int x)
{
return ch[x];
}
};
编辑:正如 πάντα ῥεῖ 所建议的,这里有更多关于我想要做什么的细节。
我试图拥有一个通用类Pixel
,它将成为处理任何类型或大小的模板。
通常是 1、2、3、4、8 或 16。类定义了一些operator
,如 +、-、* 等。
由于大多数时候Pixel<T,3>
是 BGR 像素,我想定义快速访问r
,以避免混淆g
,b
但仍将其存储为 BGR。
但是派生类还应该提供基于N
.
EDIT2:通过阅读 SergeyA 的评论,我忘了说结构Pixel
不能改变大小。
所以我认为 balki 答案是最好的,通过使用成员函数。我试图用变量来避免过多的字符,即:添加 (),但它似乎太复杂了。我仍在研究 CRTP,但我不明白,我正在阅读。
解决方案
Curiously Recurring Template Pattern (CRTP) 在这种情况下会很好地工作。在 CRTP 中,派生类用作基类的模板参数。David Vandevoorde 和 Nicolai M. Josuttis 所著的 C++ 模板 - 完整指南中的第 16.3 章奇怪重复的模板模式 (CRTP) 更详细地解释了一些事情。
从下面的评论中,使用 aunion{struct{...}...}
会导致未定义的行为(UB),但对此存在一些矛盾的意见。据我所知,它是一个 gnu 扩展,几乎每个编译器都支持。glm
例如union-structs
经常使用。
作为替代方法,您可以为r,g,b
变量使用别名(引用)。
#include <iostream>
template<typename T, std::size_t N, template<typename,std::size_t> class B >
struct Pixel
{
B<T,N> *crtp = static_cast<B<T,N>*>(this);
T& operator[](std::size_t x)
{
return crtp->ch[x];
}
Pixel& operator = (const Pixel &t)
{
crtp->ch[0] = t.crtp->ch[0];
crtp->ch[1] = t.crtp->ch[1];
crtp->ch[2] = t.crtp->ch[2];
return *crtp;
}
B<T,N> operator + (const B<T,N> &t)
{
B<T,N> tmp;
tmp[0] = crtp->ch[0] + t.crtp->ch[0];
tmp[1] = crtp->ch[1] + t.crtp->ch[1];
tmp[2] = crtp->ch[2] + t.crtp->ch[2];
return tmp;
}
B<T,N> operator - (const B<T,N> &t)
{
B<T,N> tmp;
tmp[0] = crtp->ch[0] - t.crtp->ch[0];
tmp[1] = crtp->ch[1] - t.crtp->ch[1];
tmp[2] = crtp->ch[2] - t.crtp->ch[2];
return tmp;
}
};
template<typename T, std::size_t N=3>
struct PixelBGR : Pixel<T, N, PixelBGR>
{
T ch[3];
T &r;
T &g;
T &b;
PixelBGR() : ch{},r(ch[0]),g(ch[1]),b(ch[2])
{}
PixelBGR& operator = (const PixelBGR &p)
{
ch[0] = p.ch[0];
ch[1] = p.ch[1];
ch[2] = p.ch[2];
return *this;
}
};
int main()
{
PixelBGR<int> p;
p.r = 25;
p.g = 14;
p.b = 58;
std::cout<< p[0] <<" , "<<p[1]<<" , "<<p[2] <<std::endl;
PixelBGR<int> q;
q = p;
std::cout<< q[0] <<" , "<<q[1]<<" , "<<q[2] <<std::endl;
PixelBGR<int> res1;
res1 = q + p;
std::cout<< res1.r <<" , "<<res1.g<<" , "<<res1.b <<std::endl;
PixelBGR<int> res2;
res2 = q - p;
std::cout<< res2.r <<" , "<<res2.g<<" , "<<res2.b <<std::endl;
}
结果:
25 , 14 , 58
25 , 14 , 58
50 , 28 , 116
0 , 0 , 0
使用参考的示例:https ://rextester.com/AZWG4319
使用联合结构的示例:https ://rextester.com/EACC87146
推荐阅读
- apache-kafka - Kafka Stream 只消费 N 条消息
- javascript - 使用 JS 使用正则表达式创建数字仍然创建重复数字
- r - 如何读取文件夹中的 .xlsm 文件,该文件夹使用 R 存在于不同文件夹中
- linux - Modbus RTU 到 Raspberry Pi/Linux 到 Modbus TCP
- javascript - 如何在 ReactJS 中定位 DOM 元素?
- python - 使用 Pandas 与 CSV 读取器/写入器处理和保存大型 CSV 文件
- excel - 在 Microsoft Excel 中单击按钮时如何在单元格中播放音频文件 (.Mp3)
- javascript - 在 jQuery 中切换 HTML 按钮时,时间戳不会随活动日期时间更新?
- java - 从 America/New_York 到 UTC 的时区转换错误
- python - 时变输入信号的 Pyomo 参数估计