通过const&或&&传递模板参数

13

我有这个示例程序:

#include <iostream>

template<typename Message, typename Decoration, typename PrintImpl>
void print_surrounded(Message&& msg, const Decoration& decoration, const PrintImpl& print_impl)
{
    print_impl(decoration); // should forward be used?
    print_impl(" ");
    print_impl(std::forward<Message>(msg));
    print_impl(" ");
    print_impl(decoration);
}

template<typename Message, typename PrintImpl>
void pretty_print(Message&& msg, const PrintImpl& print_impl)
{
    print_surrounded(std::forward<Message>(msg), "***", print_impl);
}

int main()
{
    pretty_print("So pretty!", [](const char* msg) {
        std::cout << msg;
    });
}

我还在Coliru上发布了它。

正如您所见,我使用了不同的方法来传递参数:

  • 消息作为通用引用被传递,因为最终需要将其转发到PrintImpl函数中。
  • 装饰被作为常量引用传递,因为它的值被使用了两次,而且我不确定使用两个forward是否安全。(第一个forward可能会将其移动掉?)
  • PrintImpl作为常量引用传递,因为我没有看到使用forward的任何理由。然而,我不确定这是否明智。(我应该使用&&传递吗?如果是,我也应该使用 std::forward 吗?)

我的选择是正确的吗?


这并不完全是我理解的 CPS 的意思。http://en.wikipedia.org/wiki/Continuation-passing_style 此外,在评论行中,我假设您是在询问是否要将 forwardprint_impl 一起使用,而不是 decoration,对吗? - sehe
@sehe 好的,我已经移除了 CPS 部分。 - StackedCrooked
只是澄清一下:这里使用“capture”一词是否正确?我认为“capture”一词是保留给由lambda表达式生成的闭包对象捕获变量的。难道“pass”(参数传递)不是正确的术语吗? - Walter
@Walter 你是对的。我改了它。 - StackedCrooked
1个回答

4

我做的选择是否正确?

大部分来说是正确的。

此处将Decoration捕获为const引用,因为它的值被使用了两次,而且我不确定使用forward两次是否安全。(第一次使用可能会移动它?)

如果需要多次使用,则不要使用std::forward,正如您所述,这样做是不安全的。

PrintImpl被捕获为const引用,因为我看不到使用forward的任何理由。

您可能想要做的是接受PrintImpl&&而不使用std::forward(将它们保留为左值),从而可以传递没有const-限定的operator()函数对象。


1
如果你非常愚蠢,你可以在函数的最后一次调用print_impl时使用std::forward<PrintImpl>(print_impl)(),以防万一你的PrintImpl有一个带有&&限定符的operator()。(注意:没有人有一个带有&&限定符的operator()。) - Yakk - Adam Nevraumont

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接