Python 返回转换为 C++ 的类型
Python Returning Types Translated to C++
我继承了 Python 中的一些代码以转换为 C++。 Python 代码根据其他函数返回的错误代码抛出异常。 Python 代码使用一个名为 errors(...)
的实用函数,该函数包含创建一个字典以将错误代码映射到异常。 returns 异常的类型和调用代码用自己的消息实例化它。
class BaseError(Exception):
pass
class Error1(BaseError):
pass
class Error2(BaseError):
pass
def errors(code):
errors_ = {
1: BaseError,
2: Error1,
3: Error2
}
try:
return errors_[code]
except KeyError:
return errors_[1]
def ReturnAnError():
# Oops an error!
return 2
try:
val = ReturnAnError()
if(val):
raise errors(val)('{} Failed'.format("Example Failed"))
except BaseError as ex:
print(ex)
我最初的想法是走一条简单的路,在 C++ 中将 Python errors(code)
函数重新定义为 void errors(uint8_t code, const char * msg)
,然后创建一个 select 语句,该语句将抛出异常本身。
是否有更优雅或更简洁的解决方案来直接翻译这段代码?特别是raise errors(val)('{} Failed'.format("Example Failed"))
在c++中最直接的翻译是什么?
如果我直接用 C++ 翻译你的代码:
#include <iostream>
#include <string>
#include <map>
class BaseError {
public:
BaseError(std::string s) : msg(s) {}
virtual ~BaseError() {} // useless because inherited classes do not have attribute to delete
friend std::ostream & operator<<(std::ostream & out, const BaseError & e) {
out << e.msg;
return out;
}
static BaseError * mk(std::string s) { return new BaseError(s); }
private:
std::string msg;
};
class Error1 : public BaseError {
public:
Error1(std::string s) : BaseError(s) {}
static BaseError * mk(std::string s) { return new Error1(s); }
};
class Error2 : public Error1 {
public:
Error2(std::string s) : Error1(s) {}
static BaseError * mk(std::string s) { return new Error2(s); }
};
typedef BaseError * (*fmk)(std::string);
fmk errors(int code)
{
const static std::map<int, fmk> error = {
{1, &BaseError::mk},
{2, &Error1::mk},
{3, &Error2::mk}
};
std::map<int, fmk>::const_iterator it = error.find(code);
return ((it == error.end()) ? error.find(1) : it)->second;
}
int ReturnAnError()
{
// Oops an error!
return 2;
}
int main()
{
try {
int val = ReturnAnError();
if (val)
throw (errors(val))("blah blah");
}
catch (BaseError * ex) {
std::cout << *ex << std::endl;
delete ex;
}
}
编译执行:
pi@raspberrypi:/tmp $ g++ c0.cc
pi@raspberrypi:/tmp $ ./a.out
blah blah
pi@raspberrypi:/tmp $
关于函数 错误 :
Python字典可以翻译成C++ std::map
据我所知,与 Python 相反,我不能在 std::map
中放入每个 class 的构造函数的地址,这就是为什么我使用 static 操作 mk 每个 class.
为了避免每次调用 errors 时创建 std::map
我定义了 error static
(和 const
明确表示我不想修改它),但这是一个优化,这不是强制性的。
在Python中非常常用异常,在C++中很少出现这种情况,这就是为什么我使用迭代器来知道代码是否是已知密钥,并且我测试它。
为了打印 classes 的实例,我重载了 operator<<
,无论如何不允许检查程序创建了一个 Error1,甚至我将代码更改为:
try {
int val = ReturnAnError();
if (val)
throw (errors(val))("blah blah");
}
catch (Error2 * ex) {
std::cout << "err2" << *ex << std::endl;
delete ex;
}
catch (Error1 * ex) {
std::cout << "err1" << *ex << std::endl;
delete ex;
}
catch (BaseError * ex) {
std::cout << *ex << std::endl;
delete ex;
}
执行的代码将是catch (BaseError * ex) {...}
如果我这样做:
try {
int val = ReturnAnError();
if (val)
throw *(errors(val))("blah blah");
}
catch (Error2 & ex) {
std::cout << "err2" << ex << std::endl;
}
catch (Error1 & ex) {
std::cout << "err1" << ex << std::endl;
}
catch (BaseError & ex) {
std::cout << ex << std::endl;
}
再次执行的代码将是 catch (BaseError & ex) {...}
(我造成了内存泄漏)。
所以打印时需要virtual
操作来区分classes,例如:
#include <iostream>
#include <string>
#include <map>
class BaseError {
public:
BaseError(std::string s) : msg(s) {}
virtual ~BaseError() {} // useless because inherited classes do not have attribute to delete
virtual void print(std::ostream & out) const { out << msg; }
static BaseError * mk(std::string s) { return new BaseError(s); }
private:
std::string msg;
};
class Error1 : public BaseError {
public:
Error1(std::string s) : BaseError(s) {}
virtual void print(std::ostream & out) const {
out << "error1 ";
BaseError::print(out);
}
static BaseError * mk(std::string s) { return new Error1(s); }
};
class Error2 : public Error1 {
public:
Error2(std::string s) : Error1(s) {}
virtual void print(std::ostream & out) const {
out << "error2 ";
BaseError::print(out);
}
static BaseError * mk(std::string s) { return new Error2(s); }
};
typedef BaseError * (*fmk)(std::string);
fmk errors(int code)
{
const static std::map<int, fmk> error = {
{1, &BaseError::mk},
{2, &Error1::mk},
{3, &Error2::mk}
};
std::map<int, fmk>::const_iterator it = error.find(code);
return ((it == error.end()) ? error.find(1) : it)->second;
}
int ReturnAnError()
{
// Oops an error!
return 2;
}
int main()
{
try {
int val = ReturnAnError();
if (val)
throw (errors(val))("blah blah");
}
catch (BaseError * ex) {
ex->print(std::cout);
std::cout << std::endl;
delete ex;
}
}
编译执行:
pi@raspberrypi:/tmp $ g++ c.cc
pi@raspberrypi:/tmp $ ./a.out
error1 blah blah
pi@raspberrypi:/tmp $
Is there a more elegant or concise solution
坦率地说,这至少不够简洁,但您的 Python 代码也不太简洁 ;-)
一个函数,每个参数的名称和类型完全相同,不能有两个 return 类型。所以没有办法允许 errors
return 不同类型的异常。即 errors
无法准确翻译。
但对于 raise errors(val)("...")
,一种简单的方法是 throw
errors
中的异常。示例代码:
#include <string>
class BaseError {
public:
std::string s;
BaseError(const std::string &_s):s(_s){}
};
class Error1 : public BaseError {
public:
Error1(const std::string &s):BaseError(s){}
};
class Error2 : public BaseError {
public:
Error2(const std::string &s):BaseError(s){}
};
void errors(int val, const std::string &s)
{
switch(val)
{
case 1:
throw BaseError(s);
case 2:
throw Error1(s);
case 3:
throw Error2(s);
default:
throw BaseError(s);
}
}
或者如果需要 object
可以 throw
在其他地方,一种方法是创建 class
可以 throw
例外。示例代码:
class errors {
public:
int val;
std::string s;
errors(int _val, const std::string _s): val(_val), s(_s){}
void raise()
{
switch(val)
{
case 1:
throw BaseError(s);
case 2:
throw Error1(s);
case 3:
throw Error2(s);
default:
throw BaseError(s);
}
}
};
我继承了 Python 中的一些代码以转换为 C++。 Python 代码根据其他函数返回的错误代码抛出异常。 Python 代码使用一个名为 errors(...)
的实用函数,该函数包含创建一个字典以将错误代码映射到异常。 returns 异常的类型和调用代码用自己的消息实例化它。
class BaseError(Exception):
pass
class Error1(BaseError):
pass
class Error2(BaseError):
pass
def errors(code):
errors_ = {
1: BaseError,
2: Error1,
3: Error2
}
try:
return errors_[code]
except KeyError:
return errors_[1]
def ReturnAnError():
# Oops an error!
return 2
try:
val = ReturnAnError()
if(val):
raise errors(val)('{} Failed'.format("Example Failed"))
except BaseError as ex:
print(ex)
我最初的想法是走一条简单的路,在 C++ 中将 Python errors(code)
函数重新定义为 void errors(uint8_t code, const char * msg)
,然后创建一个 select 语句,该语句将抛出异常本身。
是否有更优雅或更简洁的解决方案来直接翻译这段代码?特别是raise errors(val)('{} Failed'.format("Example Failed"))
在c++中最直接的翻译是什么?
如果我直接用 C++ 翻译你的代码:
#include <iostream>
#include <string>
#include <map>
class BaseError {
public:
BaseError(std::string s) : msg(s) {}
virtual ~BaseError() {} // useless because inherited classes do not have attribute to delete
friend std::ostream & operator<<(std::ostream & out, const BaseError & e) {
out << e.msg;
return out;
}
static BaseError * mk(std::string s) { return new BaseError(s); }
private:
std::string msg;
};
class Error1 : public BaseError {
public:
Error1(std::string s) : BaseError(s) {}
static BaseError * mk(std::string s) { return new Error1(s); }
};
class Error2 : public Error1 {
public:
Error2(std::string s) : Error1(s) {}
static BaseError * mk(std::string s) { return new Error2(s); }
};
typedef BaseError * (*fmk)(std::string);
fmk errors(int code)
{
const static std::map<int, fmk> error = {
{1, &BaseError::mk},
{2, &Error1::mk},
{3, &Error2::mk}
};
std::map<int, fmk>::const_iterator it = error.find(code);
return ((it == error.end()) ? error.find(1) : it)->second;
}
int ReturnAnError()
{
// Oops an error!
return 2;
}
int main()
{
try {
int val = ReturnAnError();
if (val)
throw (errors(val))("blah blah");
}
catch (BaseError * ex) {
std::cout << *ex << std::endl;
delete ex;
}
}
编译执行:
pi@raspberrypi:/tmp $ g++ c0.cc
pi@raspberrypi:/tmp $ ./a.out
blah blah
pi@raspberrypi:/tmp $
关于函数 错误 :
Python字典可以翻译成C++
std::map
据我所知,与 Python 相反,我不能在
std::map
中放入每个 class 的构造函数的地址,这就是为什么我使用 static 操作 mk 每个 class.为了避免每次调用 errors 时创建
std::map
我定义了 errorstatic
(和const
明确表示我不想修改它),但这是一个优化,这不是强制性的。在Python中非常常用异常,在C++中很少出现这种情况,这就是为什么我使用迭代器来知道代码是否是已知密钥,并且我测试它。
为了打印 classes 的实例,我重载了 operator<<
,无论如何不允许检查程序创建了一个 Error1,甚至我将代码更改为:
try {
int val = ReturnAnError();
if (val)
throw (errors(val))("blah blah");
}
catch (Error2 * ex) {
std::cout << "err2" << *ex << std::endl;
delete ex;
}
catch (Error1 * ex) {
std::cout << "err1" << *ex << std::endl;
delete ex;
}
catch (BaseError * ex) {
std::cout << *ex << std::endl;
delete ex;
}
执行的代码将是catch (BaseError * ex) {...}
如果我这样做:
try {
int val = ReturnAnError();
if (val)
throw *(errors(val))("blah blah");
}
catch (Error2 & ex) {
std::cout << "err2" << ex << std::endl;
}
catch (Error1 & ex) {
std::cout << "err1" << ex << std::endl;
}
catch (BaseError & ex) {
std::cout << ex << std::endl;
}
再次执行的代码将是 catch (BaseError & ex) {...}
(我造成了内存泄漏)。
所以打印时需要virtual
操作来区分classes,例如:
#include <iostream>
#include <string>
#include <map>
class BaseError {
public:
BaseError(std::string s) : msg(s) {}
virtual ~BaseError() {} // useless because inherited classes do not have attribute to delete
virtual void print(std::ostream & out) const { out << msg; }
static BaseError * mk(std::string s) { return new BaseError(s); }
private:
std::string msg;
};
class Error1 : public BaseError {
public:
Error1(std::string s) : BaseError(s) {}
virtual void print(std::ostream & out) const {
out << "error1 ";
BaseError::print(out);
}
static BaseError * mk(std::string s) { return new Error1(s); }
};
class Error2 : public Error1 {
public:
Error2(std::string s) : Error1(s) {}
virtual void print(std::ostream & out) const {
out << "error2 ";
BaseError::print(out);
}
static BaseError * mk(std::string s) { return new Error2(s); }
};
typedef BaseError * (*fmk)(std::string);
fmk errors(int code)
{
const static std::map<int, fmk> error = {
{1, &BaseError::mk},
{2, &Error1::mk},
{3, &Error2::mk}
};
std::map<int, fmk>::const_iterator it = error.find(code);
return ((it == error.end()) ? error.find(1) : it)->second;
}
int ReturnAnError()
{
// Oops an error!
return 2;
}
int main()
{
try {
int val = ReturnAnError();
if (val)
throw (errors(val))("blah blah");
}
catch (BaseError * ex) {
ex->print(std::cout);
std::cout << std::endl;
delete ex;
}
}
编译执行:
pi@raspberrypi:/tmp $ g++ c.cc
pi@raspberrypi:/tmp $ ./a.out
error1 blah blah
pi@raspberrypi:/tmp $
Is there a more elegant or concise solution
坦率地说,这至少不够简洁,但您的 Python 代码也不太简洁 ;-)
一个函数,每个参数的名称和类型完全相同,不能有两个 return 类型。所以没有办法允许 errors
return 不同类型的异常。即 errors
无法准确翻译。
但对于 raise errors(val)("...")
,一种简单的方法是 throw
errors
中的异常。示例代码:
#include <string>
class BaseError {
public:
std::string s;
BaseError(const std::string &_s):s(_s){}
};
class Error1 : public BaseError {
public:
Error1(const std::string &s):BaseError(s){}
};
class Error2 : public BaseError {
public:
Error2(const std::string &s):BaseError(s){}
};
void errors(int val, const std::string &s)
{
switch(val)
{
case 1:
throw BaseError(s);
case 2:
throw Error1(s);
case 3:
throw Error2(s);
default:
throw BaseError(s);
}
}
或者如果需要 object
可以 throw
在其他地方,一种方法是创建 class
可以 throw
例外。示例代码:
class errors {
public:
int val;
std::string s;
errors(int _val, const std::string _s): val(_val), s(_s){}
void raise()
{
switch(val)
{
case 1:
throw BaseError(s);
case 2:
throw Error1(s);
case 3:
throw Error2(s);
default:
throw BaseError(s);
}
}
};