2016-06-06 1 views
3

Я работаю над проектом на C++ и пытаюсь выяснить, как сделать «динамическую» переменную.Переменные в стиле Python в C++

В Python переменные могут иметь несколько типов:

variable = 0 
variable = "Hello" 

В Java, это не является также (несколько) достижимо:

Object o = 0; 
o = "Hello"; 

Из того, что я могу найти связанные с C++, нет object тип или «динамический» объект.

Причина мне это нужно, это я пытаюсь создать объект, который принимает в любой из следующих типов: int, float, char, string, bool, и позволит мне делать такие операции, как:

object o = 0; // currently an int 
o -= 2.5; // now a float 
o += "Test"; // now a string 

Есть ли какие-либо функции по умолчанию для такого рода переменных? Если нет, это можно сделать с помощью макросов, struct и т. Д.?

Я нашел такие вещи, как это:

template <typename name> 

Но не имеют ни малейшего представления о том, как использовать его.

+2

У C++ 17 будет 'std :: any', что именно вы хотите. Прямо сейчас, вы можете использовать 'boost :: any' или откатить свою собственную реализацию.Однако это не динамично. – user2296177

+0

@ user2296177 Я работаю с C++ 11 и надеюсь (но я рад отказаться от поддержки, если не возможно), чтобы иметь обратную совместимость. Я бесполезен с C++, не могли бы вы привести мне пример? Я не знаю, с чего начать ... – finnrayment

+0

Вы всегда можете создать класс, который будет иметь векторы всех типов, которые вы хотите поддерживать, а затем добавить к нему интерфейс. Но это на первый взгляд кажется очень плохой идеей с точки зрения ремонтопригодности и удобочитаемости. Я бы подумал о том, чтобы реализовать что-то подобное очень сложно и попытаться придумать совершенно другое решение. – mirosval

ответ

7

Вы можете использовать библиотеку boost.variant. Основные инструкции по использованию here. Короче говоря, это было бы что-то вроде

using var_t = boost::variant<bool,int,double,string, boost::blank_t>; 
var_t var = "hello"; 
std::cout << boost::get<std::string>(var) << '\n'; 
std::cout << var << '\n'; // if all possible stored types are streamable 

Несколько без прямой части обращается значение, не зная точного типа. Для этого требуется static visitor.

В случае, если вам интересно, какая разница между any и variant - вы не одиноки, и here is the comparison chart.

+0

Не могли бы вы уточнить? Я не знаю, как реализовать эти вещи, исходящие из всего фона Java/Python. – finnrayment

+1

Я ничего не знаю, но это может помочь, если вы не знакомы с C++: http://www.boost.org/doc/libs/1_61_0/doc/html/variant.html. То, что вы нашли о шаблонах, не то, что вы ищете. –

+0

: O Boost зависит от платформы! – finnrayment

3

Каждый язык имеет свои собственные идиоматические конструкции, и вы должны не попытаться имитировать код Python на C++. Как сказал @ user2296177, ближайший инструмент C++ (в текущей версии) является boost :: any, который также включен в C++ 17 как std :: any.

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

Если вам нужно только принять известный список типов, вы можете использовать добрые старые (исходящие из С) союзы или их ускорение с автоматическим эквивалентом boost :: variant.

Но на самом деле вам следует задаться вопросом, зачем вам это нужно, как вы намерены отслеживать фактический тип, нужно ли вам разрешать кастинг или наложение псевдонимов. Потому что за пределами динамических переменных Python C++ позволяет либо преобразовывать, либо псевдонимы между типами.

TL/DR: не пытайтесь подражать идиоме Python и тщательно анализируйте, какова ваша настоящая необходимость. Объединение может быть инструментом в некоторых случаях использования, может быть необходим указатель на пустоты в некоторых других или выделенная структура. Это действительно зависит от реального варианта использования.

+0

Проблема, которую я имею, заключается в том, что я ** потенциально ** беру ** любой ** тип объекта. Я разрабатываю программу как **, а не ** отслеживаю тип вообще, а скорее применяю операции к переменной напрямую и печатаю результаты по запросу. – finnrayment

+0

@Serge - синтаксический анализ АСТ является допустимым вариантом использования для 'variant' /' any' в C++, так же, как и синтаксический анализ тегов типа. Независимо от результатов в более дешевом/удобочитаемом/быстром (в зависимости от того, какой приоритет) код является хорошим решением, независимо от того, что это за язык, ИМХО. – bobah

+0

@frayment: Каковы операции, которые являются общими для всех типов, которые вы хотите обработать? И вы хотите обрабатывать только настраиваемые типы (могут выводиться из одного интерфейса), а также стандартные типы (строка, список, карта) или даже intrinsics (int, float, char)? И список разрешенных типов ограничен или нет? –