C++03 中的完美转发

发布于 2024-09-16 12:31:21 字数 201 浏览 19 评论 0原文

如果你有这个函数

template<typename T> f(T&);

然后尝试用它来调用它,比方说像这样的右值

f(1);

为什么 T 不被推导为 const int,使参数成为 const int&从而可以绑定到右值?

If you have this function

template<typename T> f(T&);

And then try to call it with, let's say an rvalue like

f(1);

Why isn't T just be deduced to be const int, making the argument a const int& and thus bindable to an rvalue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月寒剑心 2024-09-23 12:31:22

文档中提到这是一个潜在的解决方案< /a> 我在最近的 C++0x 转发问题中链接。

工作得相当好,但它破坏了现有的代码。考虑(直接来自文档):

template<class A1> void f(A1 & a1)
{
    std::cout << 1 << std::endl;
}

void f(long const &)
{
    std::cout << 2 << std::endl;
}

int main()
{
    f(5);              // prints 2 under the current rules, 1 after the change
    int const n(5);
    f(n);              // 1 in both cases
}

或者

// helper function in a header

template<class T> void something(T & t) // #1
{
    t.something();
}

// source

#include <vector>

void something(bool) // #2
{
}

int main()
{
    std::vector<bool> v(5);

    // resolves to #2 under the current rules, #1 after the change
    something(v[0]);
}

这也无法转发值类别(左值或右值),这在 C++03 中不是什么大问题。但由于此修复只能在 C++0x 期间完成,因此我们在转发时实际上将自己排除在右值引用之外(这是一件坏事)。我们应该努力寻求更好的解决方案。

This is mentioned as a potential solution in the document I linked in the recent C++0x forwarding question.

It would work fairly well, but it breaks existing code. Consider (straight from the document):

template<class A1> void f(A1 & a1)
{
    std::cout << 1 << std::endl;
}

void f(long const &)
{
    std::cout << 2 << std::endl;
}

int main()
{
    f(5);              // prints 2 under the current rules, 1 after the change
    int const n(5);
    f(n);              // 1 in both cases
}

Or

// helper function in a header

template<class T> void something(T & t) // #1
{
    t.something();
}

// source

#include <vector>

void something(bool) // #2
{
}

int main()
{
    std::vector<bool> v(5);

    // resolves to #2 under the current rules, #1 after the change
    something(v[0]);
}

This also fails to forward the value category (lvalue or rvalue), which isn't much of a problem in C++03. But since this fix could only be done during C++0x, we'd effectively shutting ourselves out from rvalue references when forwarding (a bad thing). We should strive for a better solution.

醉南桥 2024-09-23 12:31:22

确实如此,但前提是您将 f 声明为采用 T const &

template <typename T> void f(T &);
template <typename T> void g(T const &);

void x() { f(1); }  // error: invalid initialization of non-const reference
void y() { g(1); }  // no error

如果您声明两者 f(T &)f(T const &),它将选择 const 限定的那个:

template <typename T> void f(T &);
template <typename T> void f(T const &);

void x() { f(1); } // no error, calls f(T const &)

现在也许您会说“在第一个示例中,为什么它可以生成 int 类型的临时对象来调用 f,而它可以 已生成一个 const int 类型的临时变量并使代码编译?”我给你的最好答案是,当参数不是整数常量时,这将与重载解析行为不一致。

It is, but only if you declare f to take T const &.

template <typename T> void f(T &);
template <typename T> void g(T const &);

void x() { f(1); }  // error: invalid initialization of non-const reference
void y() { g(1); }  // no error

And if you declare both f(T &) and f(T const &), it'll choose the const-qualified one:

template <typename T> void f(T &);
template <typename T> void f(T const &);

void x() { f(1); } // no error, calls f(T const &)

Now maybe you're saying “in the first example, why does it generate a temporary of type int for the call to f when it could have generated a temporary of type const int and made the code compile?” The best answer I have for you is that that would be inconsistent with the overload resolution behavior when the argument isn't an integer constant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文