【问题标题】:implicit conversion of vector from one type to another c++向量从一种类型到另一种c ++的隐式转换
【发布时间】:2021-12-18 07:56:32
【问题描述】:

是否可以隐式将一种类型的向量转换为另一种类型?

即让这段代码工作的某种方式(显然这是我正在尝试做的一个简化问题)

std::vector<int> intVec;
intVec.push_back(1);

std::vector<double> doubleVec = intVec;
std::vector<double> doubleVec2;
doubleVec2 = intVec;

【问题讨论】:

    标签: c++ c++11 visual-c++


    【解决方案1】:

    不,不同向量类型之间没有转换(隐式或其他)。

    你可以从一个迭代器范围初始化它:

    std::vector<double> doubleVec(intVec.begin(), intVec.end());
    

    也许将其包装在一个函数中:

    template <typename To, typename From>
    To container_cast(From && from) {
        using std::begin; using std::end; // Koenig lookup enabled
        return To(begin(from), end(from));
    }
    
    auto doubleVec = container_cast<std::vector<double>>(intVec);
    

    【讨论】:

    • 谢谢,但这对我不起作用。基本上我有一个类型为vector>的巨大代码,现在我不想使用vector>,而是想使用vector。我知道如何将pair隐式转换为myClass,但是当它们在向量中时会变得很棘手。
    • @death_relic0 如果myClass 可以从pair&lt;int, int&gt; 构造,这将起作用。如果不是,那么......好吧,我不知道你会如何期望任何工作。
    • @death_relic0:如果从pairmyClass 的转换是隐式的,那么这将起作用。范围构造函数将隐式转换每个元素。
    • 我 Koenig'd 你的迭代器,只是因为。需要考虑的一件事是,如果 from 是一个右值,我们是否应该有条件地使用移动迭代器在移动为 noexcept 时从每个元素中剔除?
    • @Yakk:如果我们正在编写一个试图涵盖所有可以想象的用例的超通用库,可能。如果我们正在为 OP 的用例编写一个简单的帮助程序,可能不会。
    【解决方案2】:

    一种方法是创建转换函数。它允许您在呼叫站点表达意图:

    #include <iostream>
    #include <vector>
    
    template<class To, class From, class Allocator>
    std::vector<To, typename Allocator::template rebind<To>::other>
    implicit_convert(const std::vector<From, Allocator>& vf)
    {
        return { std::begin(vf), std::end(vf) };
    }
    
    template<class To, class ToA, class From, class FromA>
    void implicit_overwrite(std::vector<To, ToA>& to, const std::vector<From, FromA>& from)
    {
        to.clear();
        std::copy(begin(from), end(from), back_inserter(to));
    }
    
    int main(int argc, const char * argv[]) {
        using namespace std;
        std::vector<int> vi { 1, 2 , 3 };
        auto vd = implicit_convert<double>(vi);
    
        cout << "after conversion\n";
        for (const auto& i : vd) {
            cout << i << endl;
        }
    
        vi.push_back(4);
        implicit_overwrite(vd, vi);
        cout << "after copy\n";
        for (const auto& i : vd) {
            cout << i << endl;
        }
    
    
        return 0;
    }
    

    预期输出:

    after conversion
    1
    2
    3
    after copy
    1
    2
    3
    4
    

    【讨论】:

      【解决方案3】:
      template<class T, class A=std::allocator<T>>
      struct magic_vector:std::vector<T,A> {
        using base=std::vector<T,A>;
        using base::base;
        magic_vector(magic_vector const&)=default;
        magic_vector(magic_vector &&)=default;
        magic_vector& operator=(magic_vector const&)=default;
        magic_vector& operator=(magic_vector &&)=default;
        magic_vector()=default;
      
        template<class U, class B,
          class=typename std::enable_if<std::is_convertible<U,T>::value>::type
        >
        magic_vector( magic_vector<U,B> const& o ):
          base( o.begin(), o.end() )
        {}
        template<class U, class B,
          class=typename std::enable_if<
            std::is_convertible<U,T>::value
            && noexcept( T(std::declval<U&&>()) )
          >::type
        >
        magic_vector( magic_vector<U,B>&& o ):
          base(
            std::make_move_iterator(o.begin()),
            std::make_move_iterator(o.end())
          )
        {}
      };
      

      magic_vectors 是从其他magic_vectors 自动转换的向量。

      如果您有一个指向 magic_vector 的指针,您将其转换为指向 vector 的指针,然后将其作为 vector 删除,则结果是未定义的行为。 (但在实践中,我检查过的每个 C++ 实现都不会造成伤害)。然而,这是一种奇怪的处理vectors 的方式。

      vector 的使用替换为magic_vector。只要您的代码中容器的确切类型没有专门化,它就应该是一个直接替代品,除非现在它会在它们之间自动转换。

      可以让magic_vectors 自动转换为vectors 而不仅仅是magic_vectors。

      【讨论】:

        【解决方案4】:

        你可以选择这样的东西(假设 myclass 是你的类,可以从 std::pair 构造):

        #include <iostream>
        #include <vector>
        #include <utility>
        
        using std::cout;
        using std::endl;
        
        class myclass
        {
        public:
            myclass(const std::pair<int, int>& p): first_(p.first), second_(p.second) {}
            int first() {return first_;}
            int second() {return second_;}
        private:
            int first_;
            int second_;
        };
        
        template <class T>
        class myvector : public std::vector<T> 
        {
            using base = std::vector<T>;
            using base::base;
        };
        
        template<>
        class myvector<myclass> : public std::vector<myclass>
        {
        public:
            myvector(const std::vector<std::pair<int, int>>& vp):
        std::vector<myclass>(vp.begin(), vp.end()) {}
        
        };
        
        int main()
        {
            std::vector<std::pair<int, int>> vp {{12,3}, {1, 7}};
            myvector<myclass> mm = vp;
            cout<<mm[0].first(); //prints 12
        
        }
        

        您从std::vector 继承myvector,然后将其专门用于myclass。或者,您可以在命名空间中定义 myvector 并将其访问为 mynamespace::vector&lt;myclass&gt;

        【讨论】:

          猜你喜欢
          • 2020-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多