在C ++中,两种类型可以具有相同的定义而不是相同的类型。
例如,请在此处考虑A
和B
:
struct A {
int foo;
int bar;
};
struct B {
int foo;
int bar;
};
static_assert(!std::is_same<A, B>::value, "");
如果我有一个程序,那么 A
和B
是可以互换的
仅使用A
,并将A
的每个实例替换为B
,它将进行编译
并以同样的方式工作。如果你愿意,它们在“鸭子打字”的意义上是相同的,但不相同。
某些基本类型似乎发生了类似的事情。
当我在32位机器上编译C ++程序时,我发现int
和long
都代表一个带符号的32位整数,并且可以互换,但不是同一类型。
这与我使用typedef
“复制”类型时发生的情况不同。
struct A {
int foo;
int bar;
};
typedef A B;
static_assert(std::is_same<A, B>::value, "");
typedef
不会创建新类型,它会为同一类型创建新名称,
好像。
天真地,人们可能会想象典型的编译器使用某种编译器内在函数
实现基本类型。例如,你可能会想到有一些
排序模板__signed_integer
,然后在一些内部头文件中,
你找到这样的东西
typedef __signed_integer<4> int;
typedef __signed_integer<4> long;
在不同的实现方式上会有所不同。
但是,由于typedef
没有做正确的事(int
和long
是假设的
为了区别,即使它们具有相同的大小),这实际上并不是如何
它有效 - 必须有其他机制。
这个问题实际上并不是关于编译器实现的细节:相反, 问题是,在用户级标准C ++中是否存在“typedef”类型的方法 以某种方式制作副本而不是别名?
即。有没有办法获得与代码相同的效果:
struct A {
int foo;
int bar;
};
struct B {
int foo;
int bar;
};
static_assert(!std::is_same<A, B>::value, "");
但没有写两次定义,而是编写类似
的内容struct A {
int foo;
int bar;
};
typedef clone<A> B;
static_assert(!std::is_same<A, B>::value, "");
(我没有特别的用处,这只是一种好奇心。)
答案 0 :(得分:3)
您可以简单地继承:
struct A {
int foo;
int bar;
};
struct B : A{};
static_assert(!std::is_same<A, B>::value, "");
如果您愿意,仍然可以使用clone
:
#include <type_traits>
#include <utility>
struct A {
int foo;
int bar;
};
template <typename T>
struct clone : public T
{
using T::T;
template<typename ...Ts>
clone(Ts&&...ts):T{ std::forward<Ts>(ts)... } {};
};
using B = clone<A>;
static_assert(!std::is_same<A, B>::value, "");
int main()
{
A a{1,2};
B b{1,2};
}
答案 1 :(得分:3)
您可以使用模板:
template <int>
struct foobar {
int foo;
int bar;
};
using A = foobar<1>;
using B = foobar<2>;
这种方式A
和B
是不同的类型,但它允许您根据需要制作任意数量而不重复定义。