向量从一种类型到另一种类型的隐式转换 C++
implicit conversion of vector from one type to another c++
是否可以隐式将一种类型的向量转换为另一种类型的向量?
即使这段代码工作的一些方法(显然这是我正在尝试做的事情的简化问题)
std::vector<int> intVec;
intVec.push_back(1);
std::vector<double> doubleVec = intVec;
std::vector<double> doubleVec2;
doubleVec2 = intVec;
不,不同向量类型之间没有转换(隐式或其他方式)。
您可以从迭代器范围初始化它:
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);
一种方法是创建转换函数。它允许您在调用站点表达意图:
#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
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_vector
s 是从其他 magic_vector
s 自动转换的向量。
如果您有一个指向 magic_vector
的指针,您将其转换为指向 vector
的指针,然后将其作为 vector
删除,结果是未定义的行为。 (但在实践中,我检查过的每个 C++ 实现都不会造成损害)。然而,这是使用 vector
s 的一种奇怪方式。
将 vector
替换为 magic_vector
。只要您在代码中没有对容器的确切类型进行专门化,它就应该是一个直接替换,除了现在它会在它们之间自动转换。
可以做一些工作,让 magic_vector
s 自动转换为 vector
s,而不仅仅是 magic_vector
s。
你可以做这样的事情(假设我的class是你的class,可以从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<myclass>
访问
是否可以隐式将一种类型的向量转换为另一种类型的向量?
即使这段代码工作的一些方法(显然这是我正在尝试做的事情的简化问题)
std::vector<int> intVec;
intVec.push_back(1);
std::vector<double> doubleVec = intVec;
std::vector<double> doubleVec2;
doubleVec2 = intVec;
不,不同向量类型之间没有转换(隐式或其他方式)。
您可以从迭代器范围初始化它:
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);
一种方法是创建转换函数。它允许您在调用站点表达意图:
#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
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_vector
s 是从其他 magic_vector
s 自动转换的向量。
如果您有一个指向 magic_vector
的指针,您将其转换为指向 vector
的指针,然后将其作为 vector
删除,结果是未定义的行为。 (但在实践中,我检查过的每个 C++ 实现都不会造成损害)。然而,这是使用 vector
s 的一种奇怪方式。
将 vector
替换为 magic_vector
。只要您在代码中没有对容器的确切类型进行专门化,它就应该是一个直接替换,除了现在它会在它们之间自动转换。
可以做一些工作,让 magic_vector
s 自动转换为 vector
s,而不仅仅是 magic_vector
s。
你可以做这样的事情(假设我的class是你的class,可以从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<myclass>