C ++中的decltype,通用引用和转发容器

问题描述 投票:0回答:1

我正在阅读Scott Meyers的书中有关现代C ++的decltype和rvalue参考文献。我有以下代码

template <typename container, typename index>
decltype(auto) authAndAccess(container&& c, index i)  {
    std::cout << "auth and Access c type: " << typeid(c[i]).name() << std::endl;
    std::cout << "auth and Access c type expecting reference: " << typeid(std::forward<container>(c)[i]).name() << std::endl;
    return std::forward<container>(c)[i];
}

deque<int> makeStringDeque() {
    deque<int> dqContainer = { 1,2,3,4,5 };
    return dqContainer;
}

现在在主要功能我有以下

deque<int> dqContainer = { 1,2,3,4,5 };
std::cout << "Value returned by container: " << authAndAccess(dqContainer, 4) << std::endl;
authAndAccess(deque<int>{1, 2, 3, 4, 5}, 4) = 10;
std::cout << "Value returned by container and 5th element after copying: " << dqContainer[4] << endl;

我的问题是authAndAccess函数采用rvalue参数,所以容器是临时的,返回的对象是临时引用元素。但为什么输出显示为inttypeid forware,我期待int &。我知道typeid的名称功能不准确,但是为什么它不会崩溃,因为我们正在返回临时元素引用。

c++ templates pass-by-reference decltype forwarding-reference
1个回答
2
投票

我的问题是authAndAccess函数采用rvalue参数,所以容器是临时的,返回的对象是临时引用元素。

authAndAccess采用Scott称之为Universal Reference的方式,现在称为转发引用,因此它可以接受lvalue和rvalue参数。当你传递一个左值时,你得到一个左值参考,当你传递一个右值时,你得到一个左值参考。 std::forward<container>做同样的事情。如果container是左值,则得到左值,对于右值,你得到左值。

这意味着authAndAccess(dqContainer, 4)很好,因为你返回对dqContainer中仍然存在的对象的引用。在authAndAccess(makeStringDeque(), 4)你会认为你有未定义的行为,因为makeStringDeque()是一个临时的,你正在返回它的引用,但由于你不保留它,没有UB,因为引用将有效直到完整表达式结束。


但为什么输出显示为inttypeid转发,我期待int &

typeid不会告诉你是否有参考。你可以在这个最小的例子中看到

int main(int argc, char* argv[])
{
    int a = 5;
    int & b = a;
    std::cout << typeid(b).name();
}

输出i。如果你想获得类型,你可以使用声明但未定义的类模板并给它类型,你会收到一条错误消息,告诉你实际的类型是什么。如果我们将上面的代码更改为

template<typename T>
struct type;

int main(int argc, char* argv[])
{
    int a = 5;
    int & b = a;
    type<decltype(b)>{};
}

我们会得到一个错误

main.cpp:14:5: error: implicit instantiation of undefined template 'type<int &>'
    type<decltype(b)>{};

正如你所看到的,它推断出类型为int &。如果我们在你的代码中这样做,它也会给int &,因为那是c[i]的返回类型。

© www.soinside.com 2019 - 2024. All rights reserved.