使用std :: tie进行类似golang的错误处理同时还返回结果是否有缺点? (C ++ 11)

通常,执行错误处理并仍然返回值的方法是使用元组。

我想知道在不适用异常的情况下使用std :: tie在C ++中执行相同的操作是否会是一个好主意。

喜欢

std::tie(errorcode,data) = loadData();
if(errorcode)
  ...//error handling

这样做是否有不利之处(性能或其他方面)?我想通过返回值优化并不能真正起到作用,但是也许我错了。

我可以看到的一个潜在的问题案例是交叉编译器API中的用法,但这不是特定于此用法的。

我目前的操作方式是

errorcode = loadData(&data);
if(errorcode)
  ...//error handling

但是可以传递数据值。

错误代码本身是已经定义的东西,我无法更改。

编辑:我正在使用/必须使用C ++ 11

liuliuliu01 回答:使用std :: tie进行类似golang的错误处理同时还返回结果是否有缺点? (C ++ 11)

有时输出参数非常方便。假设loadData返回std::vector<T>并在循环中被调用:

std::pair<ErrorCode,std::vector<T>> loadData();

for (...) {
    ErrorCode errorcode;    
    std::vector<T> data;
    std::tie(errorcode,data) = loadData();
}

在这种情况下,loadData将必须在每次迭代中分配内存。但是,如果传递data作为输出参数,则可以重新使用先前分配的空间:

ErrorCode loadData(std::vector<T>&);

std::vector<T> data;
for (...) {
    ErrorCode errorcode = loadData(data);
}

如果以上内容无关紧要,那么您可能想看看expected<T,E>。它既代表

  • 类型T的值,期望值类型;或
  • 类型为E的值,当发生意外结果时使用的错误类型。

expected下,loadData()签名看起来像:

expected<Data,ErrorCode> loadData();

可以使用C ++ 11实现:https://github.com/TartanLlama/expected

,

错误处理有多种竞争策略。我将不讨论它,因为它超出了问题的范围,但是通过返回错误代码进行错误处理只是一种选择。考虑诸如public class Ball : MonoBehaviour { private Rigidbody2D rigidbodyBall; public SpringJoint2D[] springJoints; private GameObject speed; public static Ball instance = null; #region Life Cycle void Awake() { speed = GameObject.Find("Velocity"); springJoints = GetComponents<SpringJoint2D>(); rigidbodyBall = GetComponent<Rigidbody2D>(); gameManager = GameObject.Find("GameManager").GetComponent<GameManager>(); } private bool clickedOn = false; void Update() { if (clickedOn) { Dragging(); UIManager.instance.pauseButton.SetActive(false); UIManager.instance.totalScoreUI.gameObject.SetActive(false); } else { UIManager.instance.pauseButton.SetActive(true); UIManager.instance.totalScoreUI.gameObject.SetActive(true); } } #endregion #region Launcher #region Mouse void OnMouseDown() { SpringJointDeactivate(); clickedOn = true; } void OnMouseUp() { SpringJointActivate(); clickedOn = false; SetKinematicState(false); Invoke("SpringJointDeactivate",0.1f); } void Dragging() { Vector3 mouseWorldPointStart = transform.position; Vector3 mouseWorldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition); mouseWorldPoint.z = 0f; if (Boundary.ballInBoundary) { transform.position = mouseWorldPoint; float diffX = mouseWorldPoint.x - mouseWorldPointStart.x; //TODO for (int i = 0; i < springJoints.Length; i++) { springJoints[i].connectedAnchor = new Vector2(springJoints[i].connectedAnchor.x + diffX,springJoints[i].connectedAnchor.y); } } else { Debug.Log("Another situation!"); Debug.Log(Boundary.ballInBoundary); } } #endregion public void SpringJointActivate() { foreach (SpringJoint2D joint in springJoints) { joint.enabled = true; } } public void SpringJointDeactivate() { foreach (SpringJoint2D joint in springJoints) { joint.enabled = false; } } public Vector3[] GetSpringJointsConnectedAnchorCoord() { Vector3[] springJointsCoord = new[] { Vector3.zero,Vector3.zero }; for (int i = 0; i < springJoints.Length; i++) { springJointsCoord[i] = springJoints[i].connectedAnchor; } return springJointsCoord; } #endregion public void SetKinematicState(bool kinematicState) { rigidbodyBall.isKinematic = kinematicState; } 之类的替代方案或异常,它们在C ++中很常见,但在Go中并不常见。

如果您有一个旨在返回Go风格错误代码加值的函数,那么您的std::optional解决方案在C ++ 11或C + 14中是完美的,尽管在C ++ 17中,您宁愿使用结构化绑定。

,
  

这样做是否有不利之处(性能或其他方面)?

是的。使用tie,需要返回值的副本或移动,如果您避免使用tie,则不需要:

auto result = loadData();
if (std::get<0>(result))
    ...//error handling

当然,如果您以后再将数据复制或移动到其他地方,例如

data = std::move(std::get<1>(result));

然后使用tie,因为它更短。

本文链接:https://www.f2er.com/3073355.html

大家都在问