Имея следующий класс:
class Foo {
public:
Foo() : m_data{std::nullopt} {} // this is fine (not having m_data set),
// but only at the beginnig of objects lifetime
Foo(Bar data) : m_data{data} {}
void setData(Bar newData);
Bar getData() const;
void doJob() const; // requires m_data to be set (not std::nullopt)
void doOtherJob() const; // does not require m_data to be set.
/*...*/
private:
std::optional<Bar> m_data;
В начале, есть вероятность, что m_data
не будет установлен, но только до точки первого setData()
вызова, тогда m_data
никогда не вернется к тому, чтобы быть пустым (std::nullopt
)
Мой вопрос: могу ли я как-то сказать компилятору никогда не разрешать конструирование объектов типа Foo
с первым конструктором (по умолчанию: Foo()
), если эти объекты помечены как const
так что не будет шансов для этого типа кода:
const Foo x; // without const totally fine
// x.setData( Bar{} ); // but with it, setData cannot be called
x.doJob(); // which makes that call a 100% throw error
// and in general, whole object is less usefull now
// because it is constructed only partially,
// and cannot be finished
пройти этап компиляции?
Конечный эффект должен выглядеть так:
Bar data = getSomeData();
Foo a; // fine
Foo b{data}; // fine
const Foo c; // error, this type will never be usefull / is artificially limited,
// no logical reason to make it const
const Foo d{data}; // fine
Есть ли способ получить во время компиляции информацию о const'ness
данного нового объекта (в строительном коде или определении класса объектов), чтобы я мог использовать SFINAE или что-то еще для разделения, различения различных процедур построения для const
и not-const
объекты?
Я хочу, чтобы это было сделано во время компиляции.
Было бы неплохо иметь возможность написать что-то вроде:
class Foo{
public:
// both can still mutate everything
Foo() { /*...*/ } // but this one cant be called by const objects
Foo(Bar data) const { /*...*/ } // and this one can
};
, который не будет пытаться сделать this
указатель const Foo*
, а только притворяется, как это, поэтому объекты const
не могут вызвать этот первый "метод", но это не разрешено тем, что я знаю и проверено на это точка.
(тип Bar
не может быть установлен на какое-либо значение по умолчанию, нулевое значение. Оно либо есть, либо нет, и я бы хотел оставить его таким)
Я также не знаю, почему нельзя пометить конструкторы const
, потому что тогда (по моему мнению) не было бы проблем со всеми теми классами, где объекты могут быть построены частично, но после все равно придется быть полностью выполненным, чтобы работать должным образом или работать в своем потенциале.
Я не смог найти другого программиста с такой же проблемой, поэтому я привел расширенный пример кода, чтобы проверить, действительно ли это проблема (с другим подходом для создания const
объектов) или я просто делаю что-то неправильно путь. Есть ли какой-то шаблон дизайна, стиль программирования и т. Д., Который мне не хватает и который делает эти проблемы не существующими?
Я знаю, что на run-time
нет никакой разницы между const
и not-const
объектами, но это не главное. Я считаю, что эту проблему можно решить на compile-time
, я просто не знаю, как сказать компилятору, что я имею в виду.
Редактировать :
Создание объекта с Foo()
полезно (используя только часть его функциональных возможностей), но только если позже оно выполнит свою основную работу, которая требует m_data
.