stl向量之间的自动转换

时间:2015-09-19 12:56:39

标签: c++ vector stl template-deduction

我想要的是使用赋值运算符将std::vector<int>复制到另一个std::vector<myStruct>,其中myStruct可以分配int。所以我写了这段代码:

#include <vector>
#include <iostream>

using namespace std;

struct myStruct
{
   myStruct(int& a) : _val(a) { }
   myStruct(int&& a) : _val(a) { }

   myStruct& operator=(int& a)
   {
      _val = a;
      return *this;
   }

   int _val;
};

int main()
{
   vector<int> ivec;
   ivec.push_back(1);
   vector<myStruct> svec = ivec;

   return 0;
}

它给了我错误,因为它找不到std::vector<myStruct>std::vector<int>之间的有效转换,尽管int可以隐式转换为myStruct。另一方面,不能在类外声明赋值运算符,因此我推断手动编写运算符不是一种选择。那么在这种情况下我该怎么做呢?

***更新: 正如Blastfurnace和其他人所说,这可以使用此代码而不是赋值来解决:

vector<myStruct> svec(ivec.begin(), ivec.end());

但想象一下我想编写一个库并希望在库中处理它的情况,这样用户就可以编写std::vector<myStruct> svec = someFunction() someFunction返回std::vector<int>。难道没有解决方案吗?

3 个答案:

答案 0 :(得分:5)

您可以使用带有迭代器范围的构造函数重载:

vector<myStruct> svec(ivec.begin(), ivec.end());

答案 1 :(得分:4)

您可以改用vector<myStruct> svec(ivec.begin(), ivec.end());

您也可以使用std::copy(ivec.begin(), ivec.end(), std::back_inserter(svec));svec.assign(ivec.begin(), ivec.end());,因为如果您多次分配可能会更好,因为它可以在vector<myStruct>清除后重复使用$(function () { $(window).scroll(function () { if ($(window).scrollTop() > 0) $("body").addClass("fixed"); else $("body").removeClass("fixed"); }); });的容量。

答案 2 :(得分:1)

您最好的选择是转换功能

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {

    private let scrollView = UIScrollView()
    private let containerView = UIView()

    override func loadView() {

        self.view = UIView()
        self.view.backgroundColor = UIColor.whiteColor()
    }

    override func viewDidLoad() {

        super.viewDidLoad()

        self.scrollView.layer.borderColor = UIColor.greenColor().CGColor
        self.scrollView.layer.borderWidth = 1.0
        self.scrollView.clipsToBounds = false

        self.scrollView.translatesAutoresizingMaskIntoConstraints = false

        self.view.addSubview(scrollView)

        self.scrollView.topAnchor.constraintEqualToAnchor(self.topLayoutGuide.bottomAnchor).active = true
        self.scrollView.heightAnchor.constraintEqualToAnchor(self.view.widthAnchor).active = true
        self.scrollView.widthAnchor.constraintEqualToAnchor(self.view.widthAnchor).active = true

        self.containerView.backgroundColor = UIColor.redColor()
        self.containerView.translatesAutoresizingMaskIntoConstraints = false

        self.scrollView.addSubview(self.containerView)

        self.containerView.widthAnchor.constraintEqualToAnchor(self.scrollView.widthAnchor).active = true
        self.containerView.heightAnchor.constraintEqualToAnchor(self.scrollView.heightAnchor).active = true
    }

    override func viewDidLayoutSubviews() {

        super.viewDidLayoutSubviews()

        print("content offset: \(self.scrollView.contentOffset)")
        print("origin: \(self.scrollView.frame.origin)")
        print("they to not match visually :( <-- BROKEN !!!")
    }

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {

        return UIInterfaceOrientationMask.Portrait
    }

    override func prefersStatusBarHidden() -> Bool {

        return false
    }
}

会自动使用返回值优化,因此没有两次复制数据的开销(当你迭代&#34;其他&#34;向量时,你只需复制一次数据)。

只是为了完整起见:

通过使用自定义数据类型,可以添加自定义类型转换,但我想这通常是一个坏主意,您可能不感兴趣,无论如何:

std::vector< myStruct> convertVector( const std::vector< int> & other)
{
    return std::vector< myStruct> ( ivec.begin(), ivec.end() );
}

用法:

class IntVector: public std::vector<int>{
    public:
    //conversion operator (note a VERY BAD IDEA using this, may come in handy in few cases)
    operator myStructVector () { 
        return convertVector(*this); 
    }
}

class myStructVector: public std::vector< myStruct>{
    //....
};

无论如何,我会劝阻这样做^^