【问题标题】:Is there a way to ensure two arguments passed to a function are treated as the first and third argument in C++?有没有办法确保传递给函数的两个参数在 C++ 中被视为第一个和第三个参数?
【发布时间】:2020-05-04 05:44:01
【问题描述】:

假设有一个具有以下原型的函数:

void fun (int = 10, int = 20, int = 30, int = 40);

如果这个函数是通过传递两个参数来调用的,我们如何确保这些参数被视为第一个和第三个,而第二个和第四个被视为默认值。

【问题讨论】:

  • 函数重载转发。
  • 对参数重新排序,使第一个和第三个参数分别为第一个和第二个。在 C++ 中没有办法跳过这样的参数。
  • Named arguments 在 Python 中。

标签: c++ overloading default-arguments


【解决方案1】:
// three and four argument version
void fun (int a, int b, int c, int d = 40)
{
    ...
}

// two argument version
void fun (int a, int c)
{
     fun(a, 20, c, 40);
}

// one and zero argument version
void fun(int a = 10)
{
     fun(a, 20, 30, 40);
}

但实际上我的建议是不要。

【讨论】:

  • @Scheff 好吧,我只提供了答案,因为另一个答案不正确(详细),我想展示如何做到这一点。但通常我的回答是不要那样做。
【解决方案2】:

您可以像这样定义Args 结构:

struct Args {
   int a = 10;
   int b = 20;
   int c = 30;
   int d = 40;
};

然后你会得到以下内容:

void fun(Args);

fun({.a=60, .c=70}); // a=60, b=20, c=70, d=40

除了这种方法,您还可以使用在 C++ 中实现命名参数的NamedType 库。更多使用信息,请查看here

更新

Designated initializers 功能由 GCC 和 CLANG 扩展 提供,并且从 C++20 开始,它可以通过 C++ 标准提供。

【讨论】:

  • 哪个版本的 C++ 有 {.a=60, .c=70} 语法?以前没见过。
  • @john GCC 和 CLANG 具有实现此指定初始化程序功能的扩展。但从 C++20 开始,它是 standard 的一部分
【解决方案3】:

这个可行,它使用函数重载。

#include <iostream>
using namespace std;

void fun(int a = 10, int b = 20, int c = 30, int d = 40){
    cout << "a = " << a << "\nb = " << b << "\nc = " << c << "\nd = " << d;
}

void fun(float a, float c, int b = 20, int d = 40){
    cout << "a = " << a << "\nb = " << b << "\nc = " << c << "\nd = " << d;
}

int main(){
    cout << "Enter two numbers : ";
    float a, b;
    cin >> a >> b;
    fun(a, b);
    return 0; 
}

【讨论】:

    【解决方案4】:

    也许更优雅的方式是像这样使用std::bindstd::placeholders

    #include <functional>
    
    void fun (int = 10, int = 20, int = 30, int = 40) {}
    
    using namespace std::placeholders;
    auto bindedFun = std::bind(fun, _1, 20, _2, 40);
    
    int main()
    {
      bindedFun(1234, 5678);
    }
    

    我发现它更清晰,更容易理解。此外,它不太容易出错 imo!如果你不想有一个全局变量来保存你的绑定,你可以在本地声明它或者将你的绑定填充到一个结构中。

    【讨论】:

    • lambda 比std::bind() 更优雅(并且通常总是首选),例如:auto bindedFun = [](int a, int b){ fun(a, 20, b, 40); }
    • 是的,这也是一个解决方案,我完全同意!
    • 这并不能完全解决问题。它指出,仅当提供了 2 个参数时,该函数才应将两个参数视为第一个和第三个参数。该函数应该仍然能够支持四个参数。我认为其他人提到的函数重载是这里的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 2022-07-04
    • 1970-01-01
    相关资源
    最近更新 更多