如何检查分配给呼叫操作员结果的类型?
How to check type being assigned to result of call operator?
我正在尝试制作一个简单的矩阵 class
“mymat.h”的相关部分
#ifndef _MYMAT_H_GUARD_
#define _MYMAT_H_GUARD_
#include <iostream>
constexpr auto MYMAT_ERR_UNEXPECTED_TYPE = "Error, unexpected type!";
constexpr auto MYMAT_ERR_CODE_UNEXPECTED_TYPE = 0;
constexpr auto MYMAT_ERR_OUT_OF_BOUND = "Error, out of bound!";
constexpr auto MYMAT_ERR_CODE_OUT_OF_BOUND = 0;
template <typename T>
class MYMAT{
public:
T* data;
int x, y;
public:
MYMAT(int x, int y);
~MYMAT();
template <typename C>
void set(int x, int y, C val);
template<typename C>
bool checkType(C val) const;
void print_mat();
public:
T& operator ()(int x, int y);
private:
bool inRange(int x, int y);
};
#endif // !_MYMAT_H_GUARD_
template<typename T>
inline MYMAT<T>::MYMAT(int x, int y){
this->data = new T[x * y]();
this->x = x;
this->y = y;
}
template<typename T>
inline MYMAT<T>::~MYMAT(){
delete this->data;
}
template<typename T>
inline void MYMAT<T>::print_mat(){
int x, y;
for (y = 0; y < this->y; y++)
{
for (x = 0; x < this->x; x++)
{
std::cout << this->data[y * this->x + x] << ' ';
}
std::cout << std::endl;
}
std::cout << std::endl;
}
template<typename T>
inline bool MYMAT<T>::inRange(int x, int y){
return !((x < 1) && (x > this->x) && (y < 1) && (y > this->y));
}
template<typename T>
template<typename C>
inline void MYMAT<T>::set(int x, int y, C val){
if (this->checkType(val)) {
if (this->inRange(x, y)) {
this->data[(y - 1) * this->x + (x - 1)] = val;
}
else {
std::cout << MYMAT_ERR_OUT_OF_BOUND;
exit(MYMAT_ERR_CODE_OUT_OF_BOUND);
}
}
else {
std::cout << MYMAT_ERR_UNEXPECTED_TYPE;
exit(MYMAT_ERR_CODE_UNEXPECTED_TYPE);
}
}
template<typename T>
inline T& MYMAT<T>::operator()(int x, int y)
{
return this->data[this->x * (y - 1) + (x - 1)];
}
template<typename T>
template<typename C>
inline bool MYMAT<T>::checkType(C val) const
{
return std::is_same_v<T, C>;
}
下面是我如何调用矩阵并使用 set
方法
#include <iostream>
#include "mymat.h"
int main()
{
MYMAT<int> m(3, 3);
m.set(2, 2, 500);
m.print_mat();
m.set(2, 2, 500.0);
m.print_mat();
}
它打印
0 0 0
0 500 0
0 0 0
Error, unexpected type!
但是当调用操作符时:
#include <iostream>
#include "mymat.h"
int main()
{
MYMAT<int> m(3, 3);
m(2, 2) = 500;
m.print_mat();
m(2, 2) = 500.0;
m.print_mat();
}
它打印:
0 0 0
0 500 0
0 0 0
0 0 0
0 500 0
0 0 0
如您所见,该值已从 double 转换为 int。
如何为呼叫运营商应用 set()
中的条件?
实现你想要的:
m(2, 2) = 500.0; // do custom checks for conversions from
// right hand side to left hand side
return 从 operator()
转换 T&
是行不通的,因为您无法控制到 T
的隐式转换。在这种情况下,您无法阻止从 double
到 int
.
的转换
相反,您可以 return 您自己编写的 operator()
中的类型,这样您就拥有了对隐式转换所需的所有控制权。此类型需要保留左侧的信息,即 m
的 this
指针和 operator()
的参数。它只需要支持 operator=
来检查右侧的隐式转换:
private:
struct Wrapper
{
MYMAT *t; // holds onto the this pointer
int x, y;
template <typename C>
void operator=(C val)
{
t->set(x, y, val); // uses MYMAT::set to do the conversion checking
}
};
现在您可以这样声明您的 operator()
:
public:
Wrapper operator ()(int x, int y);
并这样定义它:
template<typename T>
inline auto MYMAT<T>::operator()(int x, int y) -> Wrapper
{
return {this, x, y};
}
这是一个 demo。
我正在尝试制作一个简单的矩阵 class
“mymat.h”的相关部分
#ifndef _MYMAT_H_GUARD_
#define _MYMAT_H_GUARD_
#include <iostream>
constexpr auto MYMAT_ERR_UNEXPECTED_TYPE = "Error, unexpected type!";
constexpr auto MYMAT_ERR_CODE_UNEXPECTED_TYPE = 0;
constexpr auto MYMAT_ERR_OUT_OF_BOUND = "Error, out of bound!";
constexpr auto MYMAT_ERR_CODE_OUT_OF_BOUND = 0;
template <typename T>
class MYMAT{
public:
T* data;
int x, y;
public:
MYMAT(int x, int y);
~MYMAT();
template <typename C>
void set(int x, int y, C val);
template<typename C>
bool checkType(C val) const;
void print_mat();
public:
T& operator ()(int x, int y);
private:
bool inRange(int x, int y);
};
#endif // !_MYMAT_H_GUARD_
template<typename T>
inline MYMAT<T>::MYMAT(int x, int y){
this->data = new T[x * y]();
this->x = x;
this->y = y;
}
template<typename T>
inline MYMAT<T>::~MYMAT(){
delete this->data;
}
template<typename T>
inline void MYMAT<T>::print_mat(){
int x, y;
for (y = 0; y < this->y; y++)
{
for (x = 0; x < this->x; x++)
{
std::cout << this->data[y * this->x + x] << ' ';
}
std::cout << std::endl;
}
std::cout << std::endl;
}
template<typename T>
inline bool MYMAT<T>::inRange(int x, int y){
return !((x < 1) && (x > this->x) && (y < 1) && (y > this->y));
}
template<typename T>
template<typename C>
inline void MYMAT<T>::set(int x, int y, C val){
if (this->checkType(val)) {
if (this->inRange(x, y)) {
this->data[(y - 1) * this->x + (x - 1)] = val;
}
else {
std::cout << MYMAT_ERR_OUT_OF_BOUND;
exit(MYMAT_ERR_CODE_OUT_OF_BOUND);
}
}
else {
std::cout << MYMAT_ERR_UNEXPECTED_TYPE;
exit(MYMAT_ERR_CODE_UNEXPECTED_TYPE);
}
}
template<typename T>
inline T& MYMAT<T>::operator()(int x, int y)
{
return this->data[this->x * (y - 1) + (x - 1)];
}
template<typename T>
template<typename C>
inline bool MYMAT<T>::checkType(C val) const
{
return std::is_same_v<T, C>;
}
下面是我如何调用矩阵并使用 set
方法
#include <iostream>
#include "mymat.h"
int main()
{
MYMAT<int> m(3, 3);
m.set(2, 2, 500);
m.print_mat();
m.set(2, 2, 500.0);
m.print_mat();
}
它打印
0 0 0 0 500 0 0 0 0 Error, unexpected type!
但是当调用操作符时:
#include <iostream>
#include "mymat.h"
int main()
{
MYMAT<int> m(3, 3);
m(2, 2) = 500;
m.print_mat();
m(2, 2) = 500.0;
m.print_mat();
}
它打印:
0 0 0 0 500 0 0 0 0 0 0 0 0 500 0 0 0 0
如您所见,该值已从 double 转换为 int。
如何为呼叫运营商应用 set()
中的条件?
实现你想要的:
m(2, 2) = 500.0; // do custom checks for conversions from
// right hand side to left hand side
return 从 operator()
转换 T&
是行不通的,因为您无法控制到 T
的隐式转换。在这种情况下,您无法阻止从 double
到 int
.
相反,您可以 return 您自己编写的 operator()
中的类型,这样您就拥有了对隐式转换所需的所有控制权。此类型需要保留左侧的信息,即 m
的 this
指针和 operator()
的参数。它只需要支持 operator=
来检查右侧的隐式转换:
private:
struct Wrapper
{
MYMAT *t; // holds onto the this pointer
int x, y;
template <typename C>
void operator=(C val)
{
t->set(x, y, val); // uses MYMAT::set to do the conversion checking
}
};
现在您可以这样声明您的 operator()
:
public:
Wrapper operator ()(int x, int y);
并这样定义它:
template<typename T>
inline auto MYMAT<T>::operator()(int x, int y) -> Wrapper
{
return {this, x, y};
}
这是一个 demo。