我目前正在编写一个适配器,用于在两个框架A< - >之间转换类型。 B.我对这些名字有点麻烦,因为在我看来,这些名字已经很长很难以理解。然后我决定以一种非常嵌套的方式使用命名空间,我很少见到其他地方。
OLD:
TypeA mylib::cvtToAtype(TypeB) {}
TypeB mylib::cvtToBtype(TypeA) {}
NEW:
TypeA mylib::cvt::to_a::type(TypeB) {}
TypeB mylib::cvt::to_b::type(TypeA) {}
你认为这是一种好的风格还是你看到了重大的缺点?我认为它看起来很干净,但如果有人决定“使用名称空间”,它可能会被误用。然后,type不是一个唯一的名称,用于标识函数正在执行的操作。另外,名为“cvt”的命名空间也可能不是超级唯一的。
您怎么看?
答案 0 :(得分:1)
所以,你开始于:
TypeA mylib::cvtToAtype(TypeB) {}
TypeB mylib::cvtToBtype(TypeA) {}
您说明的问题:功能名称“变得非常长且不可读”。你建议:
mylib::cvt::to_a::type
首先,“cvt”不会被代码的读者/维护者轻易地识别为“转换”。尾随::type
对我来说似乎毫无意义。任何名为“to_”的内容都可能是转化,因此我看不到::cvt::
级别中的重点。
无论价值多少,还有其他选择......
您可以考虑创建构造函数[explicit] TypeA::TypeA(TypeB)
和[explicit] TypeB::TypeB(TypeA)
,以便客户端使用简单:
TypeA a{b};
functionThatWantsB(TypeB{a});
如果要将函数与TypeA / B类分开,具有特化的“强制转换”样式模板是一个不错的选择:
template <typename TypeTo, typename TypeFrom>
TypeTo convert(const TypeFrom&);
template <>
TypeB convert<TypeB, TypeA>(const TypeA& a) { return TypeB{...}; }
template <>
TypeA convert<TypeA, TypeB>(const TypeB& a) { return TypeA{...}; }
客户端使用是熟悉的铸造符号:例如convert<TypeB>(a)
。这比cvtToAtype
强大得多,因为如果目标类型是抽象的 - 模板中的参数,来自using
或typedef
的别名 - 您仍然可以投射。
另一种选择是使用convert-to类型的函数参数,因此调用者不必将其作为转换函数名称或模板参数的一部分输出:
TypeA& loadFrom(TypeA&, const TypeB&) { ... }
TypeB& loadFrom(TypeB&, const TypeA&) { ... }
使用重载的编译时多态意味着每次涉及的变量在支持的类型之间发生变化时,不需要更新转换代码。