我在C ++ 0x框架中有各种类,并且想要编写函数来在它们之间进行转换。例如:
struct Foo { float v; };
struct Bar { int i; };
struct Tar { float p, q; };
void Convert(const Foo& x, Bar& y) { y.i = static_cast<int>(x.v); }
void Convert(const Tar& x, Foo& y) { y.v = x.p + x.q; }
这只是一个例子。有很多“小”课程。并非所有转换功能都有意义。
此外,有些类基本上表现得像STL容器,应该“继承”这些转换函数。
void Convert(const std::vector<Foo>& cx, std::vector<Bar>& cy) { ... }
void Convert(const std::vector<Tar>& cx, std::vector<Bar>& cy) { ... }
不,我正在寻找一种简单的方法来定义这些功能。我试过了:
template<typename X, typename Y>
void Convert(const std::vector<X>& cx, std::vector<Y>& cy) {
cy.resize(cx.size());
for(std::size_t i=0; i<cx.size(); i++) {
Convert(cx[i], cy[i]);
}
}
这很有效。
然而,有了这样的设置,我必须写
std::vector<X> cx = { ... };
std::vector<Y> cy;
Convert(cx, cy);
// when not specifying the type, one needs to use this form f(X, &Y)
使用类似
的设置template<typename X, typename Y>
std::vector<Y> Convert(const std::vector<X>& cx) {
std::vector<Y> cy(cx.size());
for(std::size_t i=0; i<cx.size(); i++) {
cy[i] = Convert(cx[i]);
}
return cy;
}
一个人必须写
std::vector<X> cx = { ... };
std::vector<Y> cy = Convert<X,Y>(cx);
// can I avoid specifying the source type with this form?
当然,在某些时候需要提到目标类型,但源类型由函数参数定义。我不想一次又一次地提到它。
是否有一种优雅的通用方法来处理这种转换函数?
编辑问题以澄清
答案 0 :(得分:1)
您是否考虑过使用ctors:
struct Bar {
int i;
explicit Bar(Foo const &f) : i(static_cast<int>(f.v)) {}
};
然后你可以这样做:
Bar x = static_cast<Bar>(some_foo);
您是否真的想要明确地提出这个问题可能会有疑问。如果你消除它(允许隐式转换),转换一个向量就变得微不足道了:
std::vector<foo> foos;
// code to populate foos ...
std::vector<Bar> bars((foos.begin()), foos.end());
至于是否要明确表达,问题是你是否可能意外地从Foo转换到Bar,让某些事情发生你真正不想要的事情。对于转换为bool
之类的问题,这是一个非常常见的问题,但从一个用户定义的类型转换为另一个类型的问题则更少。在这种情况下,关闭explicit
可以方便且合理安全。
答案 1 :(得分:1)
为什么不简单地为此目的使用构造函数?
explicit Bar(const Foo& x) : i(static_cast<int>(x.v)) {}
答案 2 :(得分:0)
由于返回值优化,您不需要使用out参数,只需使用返回值:
void Convert(const X& x, Y& y);
变为:
Y Convert(const X& x);
所以现在你可以在表达中使用它。
另请考虑使用转换构造函数或转换运算符:
Y::Y(const X&);
X::operator Y();
这些将允许类型之间的隐式转换(如果这是您想要的 - 否则您可以将它们声明为显式)。
对于处理STL容器,请使用迭代器范围:
template<class FwdIterator>
Y Convert(FwdIterator begin, FwdIterator end);
在这种风格中,它不仅与所有STL容器兼容,而且还与原始指针范围兼容。
另请注意,如果声明隐式转换构造函数或转换运算符,则可以使用std :: copy:
vector<X> xs = ...;
vector<Y> ys;
copy(xs.begin(), xs.end(), back_inserter(ys.begin()));
这会在将元素从xs转换为ys时隐含地调用用户定义的转换。
答案 3 :(得分:0)
实际上我发现了如何做到这一点。通过重新排序模板参数
template<typename Y, typename X>
std::vector<Y> ConvertTo(const std::vector<X>& cx) {
std::vector<Y> cy(cx.size());
for(std::size_t i=0; i<cx.size(); i++) {
cy[i] = Convert(cx[i]);
}
return cy;
}
可以写
std::vector<Y> cy = ConvertTo<Y>(cx);
并且编译器自动推断第二个模板类型以进行输入。不错的功能!