提问人:user22544662 提问时间:9/12/2023 最后编辑:Jan Schultkeuser22544662 更新时间:9/12/2023 访问量:55
使用 C 型变调器传递替身时出现意外的类型转换
Unexpected type conversion when using C-style variadics to pass doubles
问:
我尝试了一个变量 Args。Matrix 类与 int 一起使用,但是当我使用 double 时,当我不转换它时,我得到了 23 的错误值。我读到其他类型的类型会自动转换
- 浮点参数在浮点提升中转换为双精度 AS
- Bool、Char、short 和 Unscoped 枚举被转换为 int 或更宽的整数类型,如整数提升“我不明白为什么我得到错误的值。
#include "matrix.h"
//#include "coordinate_sys.h"
int main(){
//Coordinate_3d<double>Coordinate_3(1,2,3);
//Coordinate_3.print_console();
Matrix<double>sick_matrix(2,2,4,20.5,(double)23,23,0);
sick_matrix.print_console();
while(1){}
return 0;
}
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
#include <cstdarg>
template<typename T>
class Matrix{
private:
T * arr_ptr;
unsigned int rows;
unsigned int cols;
public:
Matrix(unsigned int rows, unsigned int cols, unsigned int args_ctr,...): rows(rows),cols(cols){
//react to false input
//--------------------------------------------------------------------------------------------
if(cols * rows < args_ctr){ //to many args
std::cout << "Matrix initilization with to many arguments" << std::endl;
exit(EXIT_FAILURE);
}
//--------------------------------------------------------------------------------------------
arr_ptr = new T[rows*cols];
va_list args;
unsigned int fill_var = 0;
va_start(args,args_ctr);
while (fill_var < args_ctr)
{
arr_ptr[fill_var] = va_arg(args,T);
fill_var++;
}
va_end(args);
}
void print_console(){for(unsigned int i = 0; i < rows*cols; i++){std::cout << arr_ptr[i] << std::endl;}}
};
#endif
我将使用变量模板参数来执行此操作,但为什么转换中会出现错误?
答:
3赞
Jan Schultke
9/12/2023
#1
问题在于,C 样式的可调参数绝对不会给你带来类型安全。 传递 a 和两个 s,并且您期望在构造函数中传递三个 s。(double)23,23,0
double
int
double
您通常应该远离 C++ 中的 C 样式可变参数。
解决方案 A -std::initializer_list
Matrix(unsigned int rows, unsigned int cols, std::initializer_list<T> args)
: rows(rows), cols(cols) {
// args.size() can be used to obtain the number of arguments
}
解决方案 B - 静态大小的矩阵
在几乎所有情况下,您都知道编译时矩阵的大小。如果将行和列转换为非类型模板参数,则许多问题变得微不足道:
template <typename T, std::size_t Rows, std::size_t Columns = Rows>
class Matrix {
private:
// ...
public:
T data[Rows * Columns];
};
你甚至不再需要构造函数,可以这样写:
using Mat3f = Matrix<float, 3>; // convenience alias
Mat3f mat{/* ... */}; // aggregate initialization, no constructor needed
如果你坚持要有一个构造函数,它可以是一个只接受一个参数的构造函数,你仍然可以使用语法。std::initializer_list<T>
Mat3f{...}
评论
23
0
double
std::initializer_list