gpt4 book ai didi

c++ - 为什么不经常使用命名参数?

转载 作者:可可西里 更新时间:2023-11-01 16:24:13 26 4
gpt4 key购买 nike

我设计了一个参数类,它允许我编写如下代码:

//define parameter
typedef basic_config_param<std::string> name;

void test(config_param param) {

if(param.has<name>()) { //by name
cout << "Your name is: " << param.get<name>() << endl;
}

unsigned long & n = param<ref<unsigned long> >(); //by type
if(param.get<value<bool> >(true)) { //return true if not found
++n;
}
}


unsigned long num = 0;
test(( name("Special :-)"), ref<unsigned long>(num) )); //easy to add a number parameter
cout << "Number is: " << num; //prints 1

该类的性能非常快:一切都只是堆栈上的引用。为了保存所有信息,我在进行堆分配之前使用了最多包含 5 个参数的内部缓冲区,以减小每个对象的大小,但这可以很容易地更改。

为什么不经常使用这种语法,重载 operator,() 来实现命名参数?是因为潜在的性能损失吗?

另一种方法是使用命名习语:

object.name("my name").ref(num); //every object method returns a reference to itself, allow object chaining.

但是,对我来说,重载 operator,() 看起来更“现代”C++,只要您不忘记使用双括号即可。性能也不会受到太大影响,即使它比正常功能慢,所以在大多数情况下可以忽略不计。

我可能不是第一个想出这样的解决方案的人,但为什么它没有更普遍呢?在我编写一个接受它的类之前,我从未见过类似上面的语法(我的示例)的东西,但对我来说它看起来很完美。

最佳答案

My question is why this syntax is not used more, overloading operator,() to implement named parameters.

因为它违反直觉,非人类可读,并且可以说是一种糟糕的编程习惯。除非您想破坏代码库,否则请避免这样做。

test(( name("Special :-)"), ref<unsigned long>(num) ));

假设我是第一次看到这个代码片段。我的思考过程是这样的:

  1. 乍一看,它看起来像 "the most vexing parse" 的例子因为你使用双括号。所以我假设 test 是一个变量,并且不得不怀疑你是否忘记写变量的类型。然后我想到这个东西实际上可以编译。之后我想知道这是否是一个立即销毁的类型测试类的实例,并且您对所有类类型都使用小写名称。
  2. 然后我发现它实际上是一个函数调用。太好了。
  3. 代码片段现在看起来像一个带有两个参数的函数调用。
  4. 现在对我来说很明显这不能是带有两个参数的函数调用,因为您使用了双括号。
  5. 所以,现在我必须弄清楚 () 中到底发生了什么.
  6. 我记得有一个逗号运算符(我在过去 5 年中从未在真正的 C++ 代码中见过它)会丢弃前面的参数。所以现在我不得不想知道 name() 的有用副作用是什么,以及 name() 是什么 - 函数调用或类型(因为你不使用大写/小写字母来区分类/函数(即Test 是一个类,但 test 是一个函数),并且您没有 C 前缀)。
  7. 查找后name在源代码中,我发现它是类。而且它会使 , 重载运算符,因此它实际上不会不再丢弃第一个参数。

看看这里浪费了多少时间?坦率地说,写这样的东西会给你带来麻烦,因为你使用语言特性使你的代码看起来与你的代码实际做的不同(你用一个参数调用函数看起来像它有两个参数或者它是一个可变函数)。这是一种糟糕的编程习惯,大致相当于重载 operator+ 来执行减法而不是加法。

现在,让我们考虑一个 QString示例。

 QString status = QString("Processing file %1 of %2: %3").arg(i).arg(total).arg(fileName);

假设我有生以来第一次看到它。这就是我的思考过程:

  1. 有一个变量status QString 类型。
  2. 它是从 QString() 类型的临时变量初始化的。
  3. ... 在调用 QString::arg 方法之后。 (我知道这是一种方法)。
  4. 我查找.arg在文档中查看它的作用,并发现它替换了 %1 -style 条目并返回 QString&。所以链.arg()通话立即有意义。请注意,像 QString::arg 这样的东西可以被模板化,你将能够为不同的参数类型调用它,而无需在 <> 中手动指定参数类型。 .
  5. 该代码片段现在有意义了,所以我转到另一个片段。

looks very more "modern" C++

“New and shiny”有时意味着“buggy and broken”(slackware linux 建立在某种类似的想法上)。如果您的代码看起来很现代,那是无关紧要的。它应该是人类可读的,它应该做它打算做的事情,并且你应该在编写它时浪费尽可能少的时间。 IE。你应该(个人建议)旨在“以最少的成本(包括维护)在最短的时间内实现最大数量的功能”,但这样做会获得最大的返回。遵循 KISS 原则也很有意义。

您的“现代”语法不会降低开发成本,不会减少开发时间,并且会增加维护成本(违反直觉)。因此,应该避免使用这种语法。

关于c++ - 为什么不经常使用命名参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10037639/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com