更好的转换功能
Better conversion functions
我在 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?
当然,在某些时候需要提及目标类型,但源类型由函数参数定义。我不想一遍又一遍地提及它。
有没有一种优雅的通用方法来处理这样的转换函数?
编辑了问题以进行澄清
为什么不简单地使用构造函数来实现此目的呢?
explicit Bar(const Foo& x) : i(static_cast<int>(x.v)) {}
您是否考虑过使用 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
可能很方便且合理安全。
由于返回值优化,您不需要使用 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 时隐式调用用户定义的转换。
实际上,我找到了如何做到这一点。通过对模板参数重新排序
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);
编译器会自动推断输入的第二种模板类型。不错的功能!
- 功能样式转换从 'int' 到 'ItemType' 的匹配转换
- 字符转换功能 std::isupper() & std::islower() C++17
- 错误:在尝试检测 std::cout 是否<< t 时,功能强制转换为数组类型;有效
- 为什么从基转换为派生提供此功能?
- 借助功能将 2D 转换为 1D 数组
- 不存在从"Magick::Color"到"MagickCore::Quantum"的合适转换功能
- 模板功能:根据类型名称进行转换
- 组件X86转换为ARM功能呼叫,其中有不同数量的参数为ARM
- 将variadic模板功能转换为许多具体功能
- 不存在从"const std::string"到"time_t"的合适转换功能
- 功能指针参数参数转换为const
- 最佳可行的转换功能
- 为什么在相同大小的功能参数中隐式转换不会发出警告
- 功能采用variadic模板包将std :: strings转换为const char *
- 为什么转换涉及两个用户定义的转换功能/构造函数
- 将C 回调功能转换为Delphi
- 将过载功能转换为专用功能模板
- 将C 功能转换为MIP
- C 概念:某些特征功能转换
- 如何从类功能转换指针