对于初学者来说,我要实现的目标的简短摘要:
std::vector<std::string> v{ "one", "two", "three", "four" };
for (const std::string& str : drop_last(v)) {
cout << str << ' ';
}
上面的代码应打印:“一二三”。
为了实现这一点,我实现了以下结构:
template <typename Container>
struct drop_last {
using const_iterator = typename Container::const_iterator;
explicit drop_last(const Container& container_) : m_container(container_) {}
const_iterator begin() {
return m_container.begin();
}
const_iterator end() {
return m_container.empty() ? m_container.end() : std::prev(m_container.end());
}
private:
const Container& m_container;
};
除了使用临时对象时,此代码工作正常(在这种情况下,断言“无法取消引用值初始化的映射/设置迭代器”):
std::vector<int> return_temporary_vector() {
vector<int> v;
// ...
return v;
}
int main(int argc_, char* argv_[]) {
for (int value : drop_last(return_temporary_vector())) {
// ...
}
// ...
}
如何调整drop_last
的结构,以便满足以下条件:
const Container& m_container;
代替Container m_container;
是不合适的。答案 0 :(得分:2)
如果您将模板函数与转发参考一起使用,则可以使用该模板函数将Container
或Container&
传递给您的课程。
#include <vector>
#include <iostream>
#include <type_traits>
template <typename Container>
struct drop_last_impl {
using const_iterator = typename std::remove_reference_t<Container>::const_iterator;
explicit drop_last_impl(Container&& container_) : m_container(std::forward<Container>(container_)) {}
const_iterator begin() {
return m_container.begin();
}
const_iterator end() {
return m_container.empty() ? m_container.end() : std::prev(m_container.end());
}
private:
const Container m_container;
};
template <typename Container>
auto drop_last(Container&& container) {
return drop_last_impl<Container>(std::forward<Container>(container));
}
std::vector<int> return_temporary_vector() {
std::vector<int> v{1,2,3};
// ...
return v;
}
int main() {
for (int value : drop_last(return_temporary_vector())) {
std::cout << value << std::endl;
}
std::vector<int> v{1,2,3};
for (int value : drop_last(v)) {
std::cout << value << std::endl;
}
// ...
}
现在, drop_last_impl
如果传递了右值,则移至std::vector<int>
;如果传递了左值,则将初始化std::vector<int>&
。
需要std::remove_reference_t
,因为如果用std::vector<int>&
实例化,我们将找不到const_iterator
。