Меня иногда раздражает необходимость инициализировать все POD-типы вручную. Э.Г.
struct A {
int x;
/* other stuff ... */
A() : x(0) /*...*/ {}
A(/*..*/) : x(0) /*...*/ {}
};
Мне это не нравится по нескольким причинам:
- Я должен повторить это в каждом конструкторе.
- Начальное значение находится в другом месте, чем объявление переменной.
- Иногда единственная причина, по которой я должен реализовать конструктор, заключается в этом.
Чтобы преодолеть это, я стараюсь вместо этого использовать свои собственные типы. То есть вместо использования int x,y;
я использую собственную векторную структуру, которая также автоматически инициализируется с помощью 0
. Я также подумал о том, чтобы просто реализовать несколько простых типов-оболочек, таких как:
template<typename T>
struct Num {
T num;
Num() : num(0) {}
operator T&() { return num; }
operator const T&() const { return num; }
T& operator=(T _n) { num = _n; return num; }
/* and all the other operators ... */
};
Это в основном решает эту проблему до сих пор для всех случаев, когда я хочу начать с 0
(это, безусловно, самые частые случаи для меня).
Спасибо Джеймсу Макнеллису за подсказку: это также можно решить с помощью boost::value_initialized
.
Теперь, не ограничиваясь POD-типами:
Но иногда я хочу инициализировать чем-то другим, и снова возникают проблемы, потому что шаблонная структура Num
не может быть легко расширена, чтобы допустить это. В основном потому, что я не могу передать числа с плавающей запятой (например, float
) в качестве параметра шаблона.
На Java я бы просто сделал:
class A {
int x = 42;
/*...*/
public A() {}
public A(/*...*/) { /*...*/ }
public A(/*...*/) { /*...*/ }
/*...*/
}
Мне очень важно, что в тех случаях, когда вы хотите всегда инициировать переменную-член одинаково во всех возможных конструкторах, вы можете записать значение init непосредственно рядом с переменной-членом, как в int x = 42;
.
То, что я пытался решить, это сделать то же самое в C ++.
Чтобы преодолеть проблему, состоящую в том, что я не могу передать значение init через параметр шаблона, я взломал некрасивый макрос:
#define _LINENAME_CAT( name, line ) name##line
#define _LINENAME( name, line ) _LINENAME_CAT( name, line )
/* HACK: use _LINENAME, workaround for a buggy MSVC compiler (http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=360628)*/
#define PIVar(T, def) \
struct _LINENAME(__predef, __LINE__) { \
typedef T type; \
template<typename _T> \
struct Data { \
_T var; \
Data() : var(def) {} \
}; \
Data<T> data; \
T& operator=(const T& d) { return data.var = d; } \
operator const T&() const { return data.var; } \
operator T&() { return data.var; } \
}
(Для других компиляторов я могу просто опустить это _LINENAME
имя для структуры и просто оставить его без имени. Но MSVC это не нравится.)
Теперь это работает более или менее так, как я хочу. Теперь это будет выглядеть так:
struct A {
PIVar(int,42) x;
/*...*/
A() {}
A(/*...*/) { /*...*/ }
A(/*...*/) { /*...*/ }
/*...*/
};
Хотя он делает то, что я хочу (в основном), я все еще не полностью доволен этим:
- Мне не нравится имя
PIVar
(что означает PreInitVar
), но я действительно не мог придумать что-то лучшее. В то же время я хочу, чтобы оно было коротким.
- Мне не нравится этот макрос взломать.
Как вы решили это? Есть лучшее решение?
Был ответ, который был снова удален, в котором говорилось, что C ++ 0x допускает в основном тот же синтаксис, что и в Java. Это правда? Тогда мне просто нужно ждать C ++ 0x.
Пожалуйста, не давайте никаких комментариев, таких как:
- "тогда просто используйте Java" / "не используйте C ++ тогда" или
- «если вам нужно что-то подобное, вы, вероятно, делаете что-то не так» или
- "просто не делай так".
Также, пожалуйста, не говорите мне не использовать его. Я знаю обо всех недостатках моего текущего решения. Пожалуйста, оставляйте комментарии о неочевидных недостатках, если вы действительно уверены, что я не знаю об этом. Пожалуйста, не просто заявляйте, что в моем текущем решении есть много недостатков. Пожалуйста, также не говорите, что использовать его не хуже. Я просто спрашиваю, знаете ли вы о лучшем решении, чем то, которое я представил здесь.