使相同的C ++types别名不兼容
我使用两种不同types的信息std::vector<int>
。 我想确保我不会不小心混合这两种用途。
总之,我想要这样的一段代码失败:
#include <vector> using A = std::vector<int>; using B = std::vector<int>; void fa(const A&); void fb(const B&); void fun() { A ax; B bx; fa(bx); fb(ax); }
即使fa
预期typesA
的参数,此代码编译。 显然, A
和B
是相同的。
什么是使这个代码正确编译的最简单的方法:
fa(ax); fb(bx);
并使此代码失败:
fa(bx); fb(ax);
当然,我可以在另一个类中包装std::vector<int>
,但是我需要重写它的接口。 另外,我可以inheritancestd::vector<int>
,但是这经常是不鼓励的。
总之,我需要两个不兼容的std::vector<int>
。
编辑
有人build议Strong typedefs可以解决这个问题。 这只是部分正确的。 如果我使用BOOST_STRONG_TYPEDEF(std::vector<int>, A)
,我需要添加一些烦人的强制转换。 例如,而不是
A ax{1,3,5};
我需要使用
A ax{std::vector<int>{1,3,5}};
而不是
for (auto x : ax) ...
我需要使用
for (auto x : (std::vector<int>)ax) ...
我认为你想要什么仍然是最好的实现:
struct A : public std::vector<int>{ using vector::vector; }; struct B : public std::vector<int>{ using vector::vector; };
它正是你想要的。 没有理由想出一些丑陋的黑客来避免干净的声明。 我看到这种分类不受欢迎的主要原因是,同样的事情应该像他们是相同的,可以交替使用。 但是,这正是你想要压制的东西,因此子types正是你想要的语句:它们具有相同的接口,但不应该因为它们不相同而使用相同的接口。
无论如何,这是一个原始痴迷的情况。 要么int
确实代表某事物, vector
是某物的集合,要么vector<int>
s代表某物。
在这两种情况下,都应该通过将原语包装成更有意义的东西来解决。 例如:
class column { int id; /*...*/ }; class row { int id; /*...*/ };
std::vector<row>
和std::vector<column>
不能互换。
当然,如果vector<int>
是真的意味着别的东西,那么相同的想法可以应用于vector<int>
而不是int
。
另外,我可以从std :: vectorinheritance,但是这经常被劝阻。
国际海事组织,这取决于情况。 一般来说可能是一个好的解决scheme
#include <vector> class VectorA : public std::vector<int> { public: VectorA() = default; ~VectorA() = default; VectorA(const VectorA&) = default; VectorA(VectorA&&) = default; VectorA& operator=(const VectorA&) = default; VectorA& operator=(VectorA&&) = default; }; class VectorB : public std::vector<int> { public: VectorB() = default; ~VectorB() = default; VectorB(const VectorB&) = default; VectorB(VectorB&&) = default; VectorB& operator=(const VectorB&) = default; VectorB& operator=(VectorB&&) = default; };
您仍然可以使用VectorA
和VectorB
作为法线vector,但不能在它们之间切换。
void acceptA(const VectorA& v) { // do something } void acceptB(const VectorB& v) { // do something } template<typename T> void acceptVector(const std::vector<T>& v) { // do something } int main(int argc, char *argv[]) { VectorA va; VectorB vb; acceptA(va); // you can only pass VectorA acceptB(vb); // same here for VectorB acceptVector(va); // any vector acceptVector(vb); return 0; }
这就是为什么你可以用C ++进行面向对象的编程,以及重用库types的基于对象的编程。
使A和B类模拟您的域中的行为。 如果这两种行为都是以字段为向量的字段来实现,那么这并不重要; 只要你不打破封装,不同载体上的所有操作都将在其范围内,不会发生混淆。
#include <vector> class A { std::vector<int> cake_orders_; public: void f() ; // can only do something to do with cake }; class B { std::vector<int> meal_worm_lengths_; public: void f() ; // can only do something to do with worms }; void fun() { A ax; B bx; af(); // has to be the right thing bf(); }