【发布时间】: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<decltype(*beg)>,这最终导致出现指向引用的指针。 -
@VTT,是的,这已经够清楚了。不太明显的是,这是本书作者 (Bjarne Stroustrup) 的错误还是我遗漏了什么?
-
如果这在书中,它会假设迭代器的延迟类型的性质不成立。请参阅下面@LogicStuff 的答案。
-
好吧,没有人是完美的,Bjarne Stroustrup 过去绝对可以避免几个大错误。而且书本代码sn-ps中的这样一个小缺陷很容易被忽略。
标签: c++ decltype iterator-traits