防止 C++14 中的 L 值实例化

Preventing L-value instantiation in C++14

本文关键字:实例化 中的 C++14 防止      更新时间:2023-10-16

C++14 中的方法可以判断它们是在 L 值还是 R 值上调用:

struct A{
  A() { puts("Ctor"); }
  void m() const & { puts("L-value"); }
  void m() const && { puts("R-value"); }
};
int main(){
  A a; //Ctor
  a.m() //L-value
  A().m(); //Ctor; R-value
}

CTOR 可以分辨出它正在构建哪种类型吗?我可以完全禁用类中 L 值的构造吗?

我有一个代理类(实际上是几个),它应该始终转换为其他东西。在不转换的情况下使用它是一个错误。我可以在运行时检测到该错误,例如,通过添加一个bool used_ = 0;成员#ifndef NDEBUG;并在我用户指定的强制转换中设置它,然后在代理类的Dtor中执行assert(used_),但是如果我能得到编译器以防止首先L-value代理实例的插入,那就更好了:

 auto x = Proxy().method1().method2(); // no
 Proxy p; // no
 Target x = Proxy(); //yes
 Target x = Proxy().method1().method2(); //yes

我可以用 C++14 做这样的事情吗?

struct temporary_only {
  static temporary_only make() { return {}; }
  temporary_only(temporary_only&&)=delete;
  int get()&& { return 3; }
private:
  temporary_only() {}
};
int main() {
  //temporary_only x; // illegal
  std::cout << temporary_only::make().get() << 'n'; // legal
}

活生生的例子。

我们禁用所有公共 ctor(包括复制/移动),因此除了通过 temporary_only::make(右值)之外,没有人可以创建temporary_only

请注意,

temporary_only&& a = temporary_only::make();

仍然有效。 在这里,我们有一个绑定到右值引用的右值,并且该右值引用本身就是具有多行生存期(作用域生存期)的左值。 这是无法阻止的。

为什么,当然:

#include <iostream>
using namespace std;
class B;
class A
{
public:
    A(B&& b) {}
    A(const B&) = delete;
};
class B {};
int main()
{
    B b;
    // A a1; <- error
    // A a2 = b; // <- error
    A a3 = move(b); // <- fine
    return 0;
}