如何仅将某些构造函数定义为仅用于非恒定对象?

时间:2018-09-04 10:15:01

标签: c++ const compile-time

具有以下课程:

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或其他方法来拆分,区分不同的构造例程constnot-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不能设置为某种默认值,即null值。它可以是,也可以不,我想保持这种状态)

我也不知道为什么不能用const来标记构造函数,因为(我认为)那时所有可以部分构造对象的类都没有问题,但是仍然必须完全实现才能正常工作或发挥其潜力。

我找不到其他遇到相同问题的程序员,所以我提出了扩展代码示例来检查这是否真的是一个问题(使用不同的创建const对象的方法)还是我只是在做一些事情错误的方式。我是否缺少任何设计模式,编程风格等,这些问题就不存在了?

我知道在run-timeconst对象之间没有区别,但这不是重点。我相信可以在not-const处解决此问题,我只是不知道如何告诉编译器我的想法。

修改: 用compile-time创建对象很有用(仅使用其功能的一部分),但是只有在以后它会完成需要Foo()的主要工作时。

1 个答案:

答案 0 :(得分:2)

否,在构造函数中无法知道对象是const还是非const。因此,您所需的功能无法实现。您有两种选择:

  • 删除默认构造函数。如果doJob是默认构造对象的错误,那么为什么不禁止这种无效状态呢?
  • 接受const Foo c;无用的事实,但是编译器不会告诉程序员。如果程序员测试他们编写的代码,那么他们应该很快就发现这一点。从类的文档中,无用也应该变得很清楚。