C++ 在if/switch的init语句中使用out/in-out参数

C++ 在if/switch的init语句中使用out/in-out参数,c++,if-statement,c++17,C++,If Statement,C++17,我想知道如何使用带有“占位符”的if/switch的init语句或类似的语句,这些语句作为out或in-out参数(如e)传递给函数。gTF(X&X) 例如,std::filesystem中的“全新”C++17 noexcept重载使用out参数通过引用传递std::error_code: bool create_directory(const std::filesystem::path& p, const std::filesystem::p

我想知道如何使用带有“占位符”的if/switch的init语句或类似的语句,这些语句作为out或in-out参数(如e)传递给函数。g<代码>TF(X&X)

例如,
std::filesystem
中的“全新”C++17 noexcept重载使用out参数通过引用传递
std::error_code

bool create_directory(const std::filesystem::path& p,
                      const std::filesystem::path& existing_p,
                      std::error_code& ec) noexcept;
using fs = std::filesystem;
inline std::error_code&& wrap_rename_ec(const fs::path& old_p,
                                        const fs::path& new_p) noexcept
{
    std::error_code ec; // Lifetime of `ec` ends after the function returns.
    fs::rename(old_p, new_p, ec);
    return std::move(ec);
}

对于返回错误代码而不是将其作为输出参数传递的函数,我将编写(伪代码):

相反,我不能在我的
if
子句中将其与init语句一起使用:

namespace fs = std::filesystem;
std::error_code ec;
fs::rename(old_p, new_p, ec);
if (ec)
{
    // handle error
}
// ec is still there
实际上,我通过使用包装器来保持调用方的代码干净:

namespace fs = std::filesystem;
inline std::error_code wrap_rename_ec(const fs::path& old_p,
                                        const fs::path& new_p) noexcept
{
    std::error_code ec;
    fs::rename(old_p, new_p, ec);
    return ec;
}

int main (void)
{
    if (auto ec = wrap_rename_ec("old_p", "new_p"); ec)
    {
         // use ec to handle error
    } // ec's lifetime ends
}
我觉得使用这样的东西很好(伪代码):

我可以使用
std::filesystem::rename
的另一个重载,它会在出错时抛出
filesystem\u错误
,但将现有路径或文件名作为新路径或文件名传递并不一定是一个必须中断程序中控制流的错误,我可能希望附加“(2)”或其他内容,因为我正在等待这种情况,这也不例外

旁注:我的问题的目的不是讨论在错误代码上使用异常,反之亦然

我不确定在描述if/switch的init语句时是否考虑了上面所述的情况,或者是否已经放弃了这种情况,而至少对我来说,找到一种优雅的方法,不需要包装函数使用if/switch的init语句处理out/in-out参数

TL;DR:从if/switch的init语句中结合out/in-out参数获利的最优雅的方式是什么?有可能吗

问候,,
我认为你问自己的问题是对的

init语句的思想是初始化一个新变量。如果您需要多个语句来初始化变量,那么您可能需要重构代码,您所做的只是一个选项

所以这里有一个折衷方案:

  • 你想要简洁的东西吗

  • 您希望能够创建一个生命周期为
    if
    for

委员会可能讨论过允许多个语句,但他们认为这会增加可读性,而不会提高代码质量(至少我是这么理解的)

不过,还是有一个小错误:

return std::move(ec);
r直接返回
ec
,而不是按值返回
&&
。编译器可能会告诉您这些

我觉得使用这样的东西很好(伪代码):

你几乎猜对了语法

你在找这个:

using fs = std::filesystem;
if (std::error_code ec; fs::rename(old_p, new_p, ec), ec) // Note that , and ; were switched.
{
    // ...
}

另外,请注意,由于访问悬挂引用,使用包装会导致UB:

bool create_directory(const std::filesystem::path& p,
                      const std::filesystem::path& existing_p,
                      std::error_code& ec) noexcept;
using fs = std::filesystem;
inline std::error_code&& wrap_rename_ec(const fs::path& old_p,
                                        const fs::path& new_p) noexcept
{
    std::error_code ec; // Lifetime of `ec` ends after the function returns.
    fs::rename(old_p, new_p, ec);
    return std::move(ec);
}
正确的书写方法是:

using fs = std::filesystem;
std::error_code wrap_rename_ec(const fs::path& old_p,
                                        const fs::path& new_p) noexcept
{
    std::error_code ec;
    fs::rename(old_p, new_p, ec);
    return ec;
}

“旁注:我的问题的目的不是讨论在错误代码上使用异常,反之亦然”-问题是什么?这篇文章只包含了你的思考。相关:我认为你不应该有返回类型
std::error\u code&
thereIMO
std::error\u code;fs::重命名(旧的、新的、ec);if(ec){}
比将所有内容塞进一个复杂的
if
语句可读性更好。讲故事的人:我在第一句话中阐述了我的问题,在最后一句话中具体说明了:从if/switch的init语句中结合out/in-out参数获取利润的最优雅的方式是什么。如果我说得不够清楚,我很抱歉。
using fs = std::filesystem;
inline std::error_code&& wrap_rename_ec(const fs::path& old_p,
                                        const fs::path& new_p) noexcept
{
    std::error_code ec; // Lifetime of `ec` ends after the function returns.
    fs::rename(old_p, new_p, ec);
    return std::move(ec);
}
using fs = std::filesystem;
std::error_code wrap_rename_ec(const fs::path& old_p,
                                        const fs::path& new_p) noexcept
{
    std::error_code ec;
    fs::rename(old_p, new_p, ec);
    return ec;
}