我正在尝试学习变元函数,所以我尝试创建一个函数“timeIt”,它接受另一个函数并调用它。
#include <chrono>
#include <iostream>
#include <string>
std::string leftPad(std::string str, unsigned len, char c = ' ') {
if (str.length() >= len)
return str;
return std::string(len - str.length(), c) + str;
}
template <typename T, typename... Args, typename... Args2>
auto timeIt(T (*func)(Args...), Args2... args) {
namespace ch = std::chrono;
auto start = ch::high_resolution_clock::now();
func(args...);
auto end = ch::high_resolution_clock::now();
return ch::duration_cast<ch::microseconds>(end - start).count();
}
int main() {
std::cout << timeIt(&leftPad, "foo", 10) << std::endl;
return 0;
}
只有当我将最后一个参数显式传递为' '时才能编译,如
timeIt(&leftPad, "foo", 10, ' ')
在这种情况下,有没有办法使用默认参数?
3条答案
按热度按时间x4shl7ld1#
你可以传递一个lambda来调用你的函数:
一般来说,你应该使用完美转发,例如
Args2&&
而不是Args2
,auto&&
而不是auto
等,然后在使用参数的地方使用std::forward
转发:x6492ojm2#
默认参数值不是函数签名的一部分。
leftPad
的签名是:std::string (std::string, unsigned, char)
函数声明中的默认参数值只是允许任何 * 直接 * 调用该函数的 * 调用站点 * 忽略该参数,编译器将在调用站点 * 使用其默认值 * 填充参数,例如:
leftPad("foo", 10)
被称为 as-if,它被写为:
leftPad("foo", 10, ' ')
当 * 间接地 * 调用函数时,情况并非如此。在
timeIt()
函数中,调用者向func
传递了一个指向函数的 * 指针 *。所有关于指定函数中的默认参数值的信息都将丢失,因为它们不是函数签名的一部分。因此,all 参数值必须显式地传递给timeIt()
,这样它们才能转发给func
。在你的例子中,
func
的类型被推导为:std::string (*func)(std::string, unsigned, char)
因此,调用者需要显式传入
' '
作为最后一个参数。正如其他答案所展示的,对
func
使用lambda将把leftPad
的 * 调用位置 * 移动到 direct 调用中,编译器能够按照预期应用默认值,例如:timeIt([&] { leftPad(foo, 10); })
被称为 as-if,它被写为:
timeIt([&] { leftPad(foo, 10, ' '); })
sr4lhrrt3#
不需要自己做繁重的工作,这已经可以通过像这样的lambda函数来完成(foo作为示例通过引用捕获):