C ++ эквивалент "динамического" ключевого слова C # 4.0? - PullRequest
5 голосов
/ 12 ноября 2010

В C # 4.0 вы можете использовать ключевое слово «dynamic» в качестве заполнителя для типа, который не известен до времени выполнения. Есть определенные угловые случаи, когда это чрезвычайно полезное поведение. Можно ли эмулировать что-либо подобное в C ++, возможно, используя функции C ++ 0x или RTTI?

Ответы [ 5 ]

4 голосов
/ 12 ноября 2010
Функция

C # dynamic сильно зависит от встроенных в .NET возможностей отражения.Поскольку стандартный C ++ предлагает почти без поддержки рефлексии, вы не можете получить подобное поведение.RTTI позволит вам безопасно использовать указатели, но это в значительной степени так.Вам еще далеко до возможности перечислять поля и методы и вызывать их динамически.

4 голосов
/ 12 ноября 2010

Не совсем.Самое близкое, что вы можете получить, это void *, но вам все равно нужно привести его к соответствующему типу, прежде чем вы сможете его использовать.

Обновление:

Попытка построить DSL типа утки, который компилируется в C ++, в основном.

Вы можете сделать это по крайней мере двумя способами:

Вариант на основе объединения

struct MyType {
  enum { NUMBER, STRING /* etc */ } type;
  union {
    double number;
    string str;
  };
};

Полиморфный класс heirarchy

class MyType {
public:
  /* define pure virtual operations common to all types */
};

class MyNumber : public MyType {
private:
  double number;
public:
  /* implement operations for this type */
};
2 голосов
/ 13 ноября 2010

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

Существует два уровня проблемы: синтаксический уровень и семантический уровень.

На уровне синтаксиса у вас есть следующий код:

dynamic d = /* something */;
d.Foo(bar); // Foo is unknown at compile time

В .NET dynamic это функция компилятора, которая вместо генерации вызов функции создает сайт вызова , который содержит имя функции и типы параметров (для перегрузки).Это означает, что если вы хотите поддерживать динамический, у вас есть для изменения компилятора.Это правда, что шаблонное метапрограммирование позволяет делать подобные вещи, но TMP по своей природе выполняется во время компиляции и, следовательно, не справится с задачей поддержки вызова во время выполнения.

Если вы не разбираетесь в синтаксисетогда вы сможете поддерживать что-то вроде этого:

dynamic d = /* something */;
d.invoke("Foo", bar);

На семантическом уровне Как сказал @ Trillian (крутое имя пользователя BTW), динамическое зависит ототражением, это не совсем верно, вы можете указать, как dynamic реализовано , и типом по умолчанию для типов CLR является отражение, поэтому тип, связанный с переменной dynamic, должен поддерживать какой-то типпроверка во время выполнения (например, COM IDispatch).Это не верно для общего случая в C ++, но если вы можете сузить свою поддержку только до типов, которые поддерживают (известный) тип проверки, вы можете реализовать dynamic в C ++ (без синтаксиса, как указано выше).

0 голосов
/ 12 ноября 2010

Это невозможно.Размеры объекта должны быть известны во время компиляции, поэтому указатель стека может перемещаться на соответствующее число байтов.Если вы не объявите тип, то компилятор не будет знать размер.C # обходит эту проблему, используя указатели на все объекты.

0 голосов
/ 12 ноября 2010

Я не могу придумать возможный путь кода, где тип значения фактически неизвестен вплоть до времени выполнения.Даже если вы связываете два модуля вместе (динамически, во время выполнения), оба они уже скомпилированы, и типы, которые они могут вернуть, также полностью определены и фактически закодированы в искаженные имена символов, которые предоставляет библиотека.

Однако вы можете отложить знание типов до тех пор, пока код не будет фактически скомпилирован.В C ++ 0x есть ключевое слово auto, которое обеспечивает вывод типа из выражения, используемого для инициализации переменной, а в текущем C ++ вы можете использовать шаблоны, например:

template<typename T>
T square(const T& someArg){
   return T*T;
}

Редактировать:основываясь на вашем комментарии к вашему вопросу, у вас, вероятно, нет ситуации, когда тип неизвестен.Более вероятно, что тип ограничен одним из нескольких (предопределенных) типов.для этого вы можете использовать тип union, предпочтительно, используя boost::variant

...