В 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
было бы скомпилировать
и работать так же. Если хотите, они одинаковы в смысле «утки», но не идентичны.
Нечто подобное происходит с некоторыми фундаментальными типами.
Когда я компилирую программы C ++ на моей 32-битной машине, я обнаруживаю, что 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, "");
?
(У меня нет особого смысла, это просто любопытство.)
Вы можете использовать шаблоны для этого:
template <int>
struct foobar {
int foo;
int bar;
};
using A = foobar<1>;
using B = foobar<2>;
Сюда A
а также B
бывают разных типов, но это позволяет вам делать столько, сколько вы хотите, без повторения определения.
Вы можете просто наследовать:
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};
}