2

我无法理解为什么我的代码不能在这里编译。我从标准库中收到很多错误消息,大致如下

main3.cpp:10:20:   required from ‘void addAndCout(T&&) [with T = const char (&)[11]]’
main3.cpp:20:28:   required from here
/usr/include/c++/5/bits/alloc_traits.h:450:27: error: forming pointer to reference type ‘const char (&)[11]’
       using pointer = _Tp*;
                           ^
/usr/include/c++/5/bits/alloc_traits.h:453:39: error: forming pointer to reference type ‘const char (&)[11]’
       using const_pointer = const _Tp*;

这对我来说没有意义,因为我认为 T&& 在没有推导 T 时是一个通用引用,它应该能够绑定到右值或左值。发布的这个示例是我试图从 Scott Meyer 的“Effective Modern C++”中复制一段我正在阅读关于通用引用的部分。书中示例的照片

我只是想知道为什么这不会编译或者我在这里缺少什么,因为据我所知,它实际上与示例相同。

#include <iostream>
#include <vector>
#include <string>
using std::cout;
using std::endl;

template<typename T>
void addAndCout(T &&name)
{
    std::vector<T> v;

    cout << name << endl;
    v.emplace_back(std::forward<T>(name));
}

int main(int argc, char **argv)
{
    std::string name {"test"};

    addAndCout(std::string("rvalue")); // FINE      move rvalue instead of copying it
    addAndCout("New string");          // ERROR     make a new string instead of copying
    addAndCout(name);                  // ERROR     copy lvalue
}
4

2 回答 2

3

不能有一个vector引用,也不能有一个 C 样式数组的向量。std::vector<T> v;当参数是左值和/或 C 样式数组时,该行无法编译。

您的代码与书中的不同之处在于您这样做std::vector<T> v;,而本书没有。

为了支持这种用法addAndCout(name);,您可以将向量定义更改为:

std::vector< typename std::remove_cv<typename std::remove_reference<T>::type>::type > v;

(这remove_cv是因为也不能有 const 对象的向量)。

为了支持 C 风格的数组,添加一个额外的重载是最简单的:

template<typename T, size_t N>
void addAndCout(T (&name)[N])
{
     // do whatever...
}
于 2018-05-24T23:00:37.820 回答
1
  • 当你这样做addAndCout(std::string("rvalue"));是右值引用和模板参数 T 是 std::string 并且 this::std::vector<std::string> v;是有效的。
  • 但是当你这样做时,addAndCout("New string");T 被推断为对 const char 数组的引用,并且你不能有引用向量
  • 当你这样做时,addAndCout(name);你正在传递左值 ref,并且 T 变得std::string&相似,你不能有参考向量。
于 2018-05-24T23:27:57.053 回答