下面的代码段汇编了一个非常重要的警告。
override func viewDidLoad() {
super.viewDidLoad()
for view in view.subviews {
if view is UIScrollView {
(view as! UIScrollView).delegate = self
break
}
}
extension PageViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers?.index(of: viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else {
return nil
}
guard (orderedViewControllers?.count)! > previousIndex else {
return nil
}
print("in viewControllerBefore")
return orderedViewControllers?[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers?.index(of: viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = orderedViewControllers?.count
guard orderedViewControllersCount != nextIndex else {
return nil
}
print("in viewControllerAfter")
return orderedViewControllers?[nextIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed {
// Get current index
let pageContentViewController = pageViewController.viewControllers![0]
currentIndex = (orderedViewControllers?.index(of: pageContentViewController))!
}
self.nextIndex = self.currentIndex
}
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
print("willTransitionTo")
let controller = pendingViewControllers.first
if let i = viewControllers?.index(of: controller!) {
print("Jason is at index \(i)")
self.currentIndex = i
} else {
print("Jason isn't in the array")
}
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return self.currentIndex
}
}
extension PageViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
/* The iOS page view controller API is broken. It lies to us and tells us
that the currently presented view hasn't changed, but under the hood, it
starts giving the contentOffset relative to the next view. The only
way to detect this brain damage is to notice that the content offset is
discontinuous, and pretend that the page changed.
*/
let poop = self.lastPosition + (0.9 * scrollView.bounds.size.width)
print("poop is \(poop)")
if (self.nextIndex > self.currentIndex) {
/* Scrolling forwards */
if (scrollView.contentOffset.x < (self.lastPosition - (0.9 * scrollView.bounds.size.width))) {
self.currentIndex = self.nextIndex;
}
} else {
/* Scrolling backwards */
if (scrollView.contentOffset.x > (self.lastPosition + (0.9 * scrollView.bounds.size.width))) {
self.currentIndex = self.nextIndex;
}
}
/* Need to calculate max/min offset for *every* page, not just the first and last. */
let minXOffset = scrollView.bounds.size.width - (CGFloat(self.currentIndex) * scrollView.bounds.size.width);
let maxXOffset = (CGFloat(((viewControllers?.count)! - self.currentIndex)) * scrollView.bounds.size.width)
if (!self.shouldBounce) {
let scrollBounds = scrollView.bounds;
if (scrollView.contentOffset.x <= minXOffset) {
scrollView.contentOffset = CGPoint(x: minXOffset, y: 0)
} else if (scrollView.contentOffset.x >= maxXOffset) {
scrollView.contentOffset = CGPoint(x: maxXOffset, y: 0)
}
scrollView.bounds = scrollBounds
}
self.lastPosition = scrollView.contentOffset.x
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
var scrollOffset = targetContentOffset.pointee
let minXOffset = scrollView.bounds.size.width - (CGFloat(self.currentIndex) * scrollView.bounds.size.width);
let maxXOffset = (CGFloat(((viewControllers?.count)! - self.currentIndex)) * scrollView.bounds.size.width)
if (!self.shouldBounce) {
if (scrollView.contentOffset.x <= minXOffset) {
scrollOffset = CGPoint(x: minXOffset, y: 0)
} else if (scrollView.contentOffset.x >= maxXOffset) {
scrollOffset = CGPoint(x: maxXOffset, y: 0)
}
}
}
}
在#include <map>
#include <vector>
template <typename iterator>
const std::pair<int, float> &foo(iterator it) {
return *it;
}
int main() {
std::vector<std::pair<int, float>> vector;
std::map<int, float> map;
vector.push_back(std::make_pair(0, 0.0));
map.insert(std::make_pair(0, 0.0));
const std::pair<int, float> &r1 = foo(vector.begin());
const std::pair<int, float> &r2 = foo(map.begin());
if (r1 != r2) {
return 1;
}
return 0;
}
期间,std::pair<const int, float>
隐式转换为std::pair<int, float>
,会产生悬空参考。
foo(map.begin())
在这种情况下,我们可以将ref2.cpp: In instantiation of ‘const std::pair<int, float>& foo(iterator) [with iterator = std::_Rb_tree_iterator<std::pair<const int, float> >]’:
ref2.cpp:16:52: required from here
ref2.cpp:7:11: warning: returning reference to temporary [-Wreturn-local-addr]
return *it;
^~
的类型调整为r2
。然而,在一般情况下,将std::pair<const int, float>
的两个调用的结果分配给类型兼容的引用将是有用的。例如,对foo()
的调用可能会包含在另一个始终返回foo()
的函数中。
可以以一种解决const修饰符错位的方式进行参考赋值吗?
答案 0 :(得分:2)
修改强>
问题实在是让std::pair<K,V>
与std::pair<const K,V>
合作; vector<>
和map<>
是红鲱鱼。 (请参阅讨论here,了解std::map<>
中键为const
的原因。)
更好的示例代码可能是:
#include <vector>
template <typename iterator>
const std::pair<const int, float>& bar(iterator it)
{
return *it;
}
int main()
{
const std::vector<std::pair<const int, float>> v1{ std::make_pair(0, 0.0f) };
bar(v1.begin());
const std::vector<std::pair<int, float>> v2{ std::make_pair(0, 0.0f) };
bar(v2.begin());
return 0;
}
根据您的评论,您真正要弄清楚的是如何使std::map<>
迭代器像[{1}}一样工作;在两种情况下,结果都应为std::vector<>
,而不是std::pair<>
。
有了这个,我写了这个黑客;我确信它有问题和/或可以改进:
std::pair<const int, ...>
答案 1 :(得分:1)
您可能会改变:
const auto& remove_const(const std::pair<const int, float>& p) {
return reinterpret_cast<const std::pair<int, float>&>(p); // :-(
}
template <typename iterator>
const std::pair<int, float> &foo(iterator it) {
return remove_const(*it);
}
为:
template <typename iterator>
const std::pair<int, float> &foo(iterator it) {
return *it;
}
这需要c ++ 14,以便继续使用c ++ 11:
template <typename iterator>
decltype(auto) foo(iterator it) {
return *it;
}