Есть ли способ имитировать «strongdef»?

Как вы, наверное, знаете, typedef больше похож на псевдоним в C ++, а не на новый тип, подробности можно посмотреть здесь:
http://dlang.org/cpptod.html#typedefs
Мне действительно не нравится решение, предложенное в ссылке, поэтому мне интересно, есть ли лучший способ?

13

Решение

Существует только один способ ввести новый тип в C ++ — с помощью ключевого слова class (union/struct/class/enum…). Есть способы скрыть эти вещи за макросами и сделать эти новые типы такими же интуитивно понятными, как и старые (см. BOOST_STRONG_TYPEDEF), но факт остается фактом, что это единственный способ ввести этот новый тип.

Представь, что у тебя был newtype ключевое слово, которое делает сильный typedef:

newtype foo = int; // with 'using' alias syntax

Как будут работать преобразования в этот тип и из него? Без преобразований вы никогда не сможете присвоить какое-либо значение объекту вашего нового типа. Только явные преобразования могут показаться интуитивно понятными, но что если вы действительно хотите неявные преобразования, и все же сможете перегружать? Ну, удачи. Возможно, вы сможете добавить все виды синтаксиса, чтобы оставить решение за пользователем, но я уверен, что вы всегда можете придумать угловые случаи, которые требуют нового синтаксиса. Просто сделай это struct, скройте это за макросом и покончите с этим.

7

Другие решения

Универсальный макрос «нет времени создавать правильный интерфейс»:

#define STRONG_CLASS_TYPEDEF(oldType, newType) \
struct newType : private oldType {             \
template<typename... T>                    \
newType(T... foo) : oldType(foo...) {}     \
oldType* operator->() { return this; }     \
oldType& operator*() {return *this;}       \
};

Если ваш компилятор не поддерживает шаблоны с переменным числом аргументов, вам нужно будет вручную вставить любые необходимые вам конструкторы. В основном это наследующий конструктор build-your-own.

К сожалению, я не думаю, что можно ограничить неявное приведение нового типа к базе, но раскрыть все его открытые поля. Есть несколько обходных путей:

Вы можете просто using oldType::X; все методы и переменные, которые вам нужны. Это определенно лучшее решение, но оно требует времени.

Или используйте перегрузку оператора скрытой стрелкой и вызовите foo->method();, Или «разыменование» нового сильного типа в базовый тип. Это в основном просто необычный актерский состав. Но учитывая operator oldType() (явно или нет) даже не работает с частным наследованием …

Во всяком случае, вот сильный тип для std::string а также Name пример.

struct Name : private std::string {
template<typename... T>
Name(T... foo) : std::string(foo...) {}

std::string* operator->() { return this; }
const std::string& operator*() {return *this;}
//The above is obviously a bad idea if you want to use this alongside pointers

using std::string::resize;
using std::string::size;
using std::string::insert;
using std::string::operator[];
// etc.
//Simplest to use, but a bit more to set up
};

Кроме того, вам придется обернуть перегрузки операторов, не являющихся членами (std :: string == в этом примере).

bool operator==(Name& lhs, Name& rhs) { return *lhs == *rhs; }
//Note: "Dereference" turns it into a std::string, as above

Честное предупреждение, я не испытал ничего, кроме базовой механики. Это может добавить (очень) небольшое количество накладных расходов. Но фактически пустой класс наверное оптимизирован прочь

2

использование BOOST_STRONG_TYPEDEF создать «strongdefs» в C ++. Для этого нет встроенной функции языка.

Тем не менее, было бы интересно узнать реальную проблему, которую вы пытаетесь решить, потому что я нашел необходимость в не псевдонимах. typedefбыть очень минимальным в коде, над которым я работал.

1

Новые типы в C ++ могут быть получены только путем объединения подтипов. Но поскольку перегрузка функции основана на статическом типе, все операции и функции должны быть объявлены повторно.

C ++ typedefs как D aliasэс.

В случае, если начальный тип является классом или структурой, наследование может как-то помочь (по крайней мере, операции могут работать как со старыми параметрами), но все относится к типу возвращаемого значения и преобразование должно быть переопределено правильно, в противном случае все преобразовывается безразлично вверх и вниз, таким образом исчезая Преимущество нового типа.

0

В C ++ есть много способов выполнить проверку типов.
Рассмотрим следующий код, основная идея такая же, как в примере, приведенном в ссылке, но я думаю, что это более просто:

struct Handle2 {void * ptr;} ;
void bar(Handle2) {}
void foo(void *) {}

int main() {
Handle2 h2 = {(void*)-1};
foo(h2); //! won't pass through compiling
bar(h2);
}
0
По вопросам рекламы [email protected]