c++ - 在模板方法c ++中传递结构参数
问题描述
我在将参数传递给类模板时遇到问题
struct Car {
int id;
char *model;
int date;
int cost;
};
template <class T>
class Set
{
private:
int *a;
int _size;
map<int, T> data;
public:
//some methods before
void insert(T x)
{
int num;
if (std::is_same<T, Car>::value)
num = x.id;
if (num >= 0 && num < (_size << 5))
throw "Element is out of set size!";
a[num / 32] = a[num / 32] | (1 << (num % 32));
if (std::is_same<T, Car>::value)
data.insert(make_pair(num, x));
}
};
我的insert
方法应该同时接受int
类型和Car
结构。但是 Visual Studio 说我有编译错误num = x.id;
应该x
是一个类、结构或联合。我可以传递指向这个函数的指针,但我不能传递像class.insert(5)
. 我该如何解决它,或者如何使方法既接受指向结构变量的指针又接受常规变量的指针,而无需对其中一种类型进行另一种规范?
解决方案
是的,这是很多人都在努力解决的问题。让我们看看你的模板方法被剪断:
void insert(T x)
{
int num;
if (std::is_same<T, Car>::value)
num = x.id;
//...
这里的问题是if
语句在运行时进行语义评估(即使编译器可以优化分支,因为它会在编译时知道值),因此,编译器需要“假装”为两个分支生成代码。附带说明一下,当不采用分支时,您的num
保持统一化,这是未定义的行为。
在您的情况下,这意味着即使T
不是Car
,语义上的代码仍然需要为num = x.id
. 显然,int.id
这不是一个有效的说法。
要使用 C++17 解决此问题,您将使用if constexpr
:
if constexpr (std::is_same<T, Car>::value) //...
Constexpr if
s 保证在编译时被评估,属于未采用分支的代码不会被评估。
在 C++17 之前的世界中,您通常可以使用标签调度或 SFINAE。我总是更喜欢标签调度,因为我认为它比 SFINAE 更直接。标签调度依赖于使用函数重载,在你的情况下会是这样的(因为不清楚你的代码在传递时会做什么int
,我会假装你需要设置num
为 int 传递:
int get_id(const Car& car) {
return car.id;
}
int get_id(int v) {
return v;
}
void insert(const T& t) {
int num = get_id(t);
// ...
请注意,在这种特殊情况下,它甚至不是标签调度,因为情况非常简单。
推荐阅读
- php - 如何在 laravel spatie 中更新/编辑 custom_properties?
- javascript - 如何延迟/开始/去抖动获取数据,直到用户停止输入?
- c++ - 为什么这个 constexpr 不在可变参数函数模板常量中?
- python - 如果此列表中的值不在此嵌套字典的键之一内,如何删除该值?
- ffmpeg - ffmpeg 输出无法在多个设备上播放
- jmeter - __FileToString 方法在请求失败的 Http 请求正文中添加一些垃圾字符串“# JMeter 生成的头文件”
- c++ - 有条件地删除 C++ 单链表中的元素
- javascript - 查找 JS 数组中的最大数并返回变量名
- swift - 添加换行符后 UITextView 高度变为可滚动
- mysql - HMAC SQL Server 转 MySQL 功能