【问题标题】:Why decltype() yelds a pointer to reference?为什么 decltype() 会产生一个指向引用的指针?
【发布时间】:2018-02-09 08:17:54
【问题描述】:

我正在尝试更好地了解iterator_traits,并在 C++ 教科书中找到了一段代码。因此,我添加了一些代码以使其可执行,目的是了解该编译时机制的行为。完整的程序如下所示:

template<typename C>
    using Iterator_type = typename C::iterator;  

template<typename Iter>
    using Iterator_category = typename std::iterator_traits<Iter>::iterator_category;   

template<typename Ran>                                          
void sort_helper(Ran beg, Ran end, std::random_access_iterator_tag)   
{
    sort(beg, end);   
}

template<typename For>                                     
void sort_helper(For beg, For end, std::forward_iterator_tag)   
{
    std::vector<decltype(*beg)> v {beg, end};   
    sort(v.begin(), v.end());
    copy(v.begin(), v.end(), beg);              
}

template<typename C>
void sort(C& c)
{
    using Iter = Iterator_type<C>;
    sort_helper(c.begin(), c.end(), Iterator_category<Iter>{});
}

void test(std::vector<std::string>& v, std::forward_list<int>& lst)
{
    sort(v);     
    sort(lst);   
}

template<typename C>
void print(C& c)
{
    for(auto it = c.begin(); it != c.end(); ++it) {
        std::cout << *it << '\n';
    }
    std::cout << '\n';
}

int main()
{
    std::vector<std::string> v { "Bicycle", "Hoovercraft", "Rocket", "Airplaine", "Bus", "Submarine" };
    print(v);

    sort(v);
    print(v);

    std::forward_list<int> lst { 2, 81, 3, 0, 4, 34, 23, 11 };
    print(lst);

    sort(lst);
    print(lst);

    return 0;
} 

编译失败,提示给出了一个引用指针:

memory:1723:16: error: 
  'pointer' declared as a pointer to a reference of type 'int &'
typedef _Tp*              pointer;

错误堆栈带来以下行:

in instantiation of template class 'std::__1::vector<int &,     std::__1::allocator<int &> >'
  requested here
std::vector<decltype(*beg)> v {beg, end};

Mac OS 和带有 g++Linux 机器上编译。

我设法修改了涉及的部分,如下所示:

auto i = *beg;
std::vector<decltype(i)> v {beg, end};

您能否更清楚地解释为什么decltype() 函数会返回指向引用的指针?我已经阅读了一些关于 SO 上的 decltype 类型函数的其他问题,并且也阅读了规范,但没有让我走上正确的道路,检查输出消息的完整编译器堆栈也没有任何帮助。

提前感谢您的考虑。

【问题讨论】:

  • decltype 产生一个引用,但真正的错误是您正在尝试构建一个引用向量 std::vector&lt;decltype(*beg)&gt;,这最终导致出现指向引用的指针。
  • @VTT,是的,这已经够清楚了。不太明显的是,这是本书作者 (Bjarne Stroustrup) 的错误还是我遗漏了什么?
  • 如果这在书中,它会假设迭代器的延迟类型的性质不成立。请参阅下面@LogicStuff 的答案。
  • 好吧,没有人是完美的,Bjarne Stroustrup 过去绝对可以避免几个大错误。而且书本代码sn-ps中的这样一个小缺陷很容易被忽略。

标签: c++ decltype iterator-traits


【解决方案1】:

问题在于decltype 产生了一个引用类型(你不能将std::vector 设为)。
为什么会这样,here 得到了深入的回答。

您可以通过以下两种方式之一修复它:

  • 使用std::remove_reference&lt;decltype(*beg)&gt;::type
  • 使用std::iterator_traits&lt;For&gt;::value_type

【讨论】:

  • std::vector&lt;typename std::remove_reference&lt;decltype(*beg)&gt;::type&gt; v {beg, end};std::vector&lt;typename std::iterator_traits&lt;For&gt;::value_type&gt; v {beg, end}; 都给出了更好的解释。
猜你喜欢
  • 1970-01-01
  • 2018-12-25
  • 1970-01-01
  • 2020-10-28
  • 2022-10-14
  • 2021-12-04
  • 1970-01-01
  • 2012-07-23
  • 2011-11-18
相关资源
最近更新 更多