有没有办法禁用非常规类型的自动声明?

alf*_*lfC 10 c++ auto c++11 regular-type

更新:有人建议auto在某些情况下改变其含义.

Joel Falcou等人对"自动"变量和论证隐含评价.

隐含评估应:

  1. 使类实现者能够指示在auto语句中评估此类的对象;
  2. 使它们能够确定评估对象的类型;

...


C++ 11的auto关键字很棒.

但是在我看来,如果一个类型是非常规的(参见例如,在移动语义的上下文中什么是"常规类型"?),则使用auto变得棘手.

有没有办法禁用auto这种类型的声明?

假设有一个ref模拟引用的类

double 5.;
ref<double> rd = d; // `ref` behaves like a reference, so it is not a regular type
ref<double> rd2 = rd; // `ref` can be (syntactically) copy constructible, (it is not regular for other reason)
auto r = rd; // now r is not `double`, but EVEN WORST it is `ref<double>`.
Run Code Online (Sandbox Code Playgroud)

(在现实生活中,这将是一个更复杂的课程,重要的一点是,手头的课程不规律.)

我发现auto r = rd不工作的唯一方法(给出编译错误)是使类不可复制,但是我需要类具有复制构造函数(具有特殊语义,但仍然是复制构造函数).

有没有办法以auto r = rd某种方式禁用语法?什么时候decltype(rd)不规律.

(更好的方法是能够以某种方式告诉编译器auto应该做什么).

注意:这不是一个非常人为的问题,可以看出这类问题是核心问题std::vector<bool>::reference(也是一个参考包装器).禁用(某种程度上)语法auto b = v[10]不会解决问题,std::vector<bool>但会使得糟糕的使用更加困难.

我错过了什么吗?我应该改变设计的其他部分吗?如果非普通班有一种特质,这将有助于编译器确定一个更一般的汽车(例如演绎boolauto b = v[10]地方std::vector<bool> v.)

Yak*_*ont 3

复制构造函数意味着您希望复制该类。auto x = y;复制yx.

如果您想要一个超级特殊的副本,并且不想自动运行,则可以使用代理对象。

template <class T>
struct pseudo_copy;

template <class T>
struct pseudo_copy<T const&> {
  T const& t;

  // T const& can be initialized from T&&:
  pseudo_copy(T const& tin) :t(tin) {}
  pseudo_copy(T&& tin): t(tin) {}
  pseudo_copy(pseudo_copy const&) = delete;
};

template <class T>
struct pseudo_copy<T&&> {
  T&& t;
  pseudo_copy(T&& tin): t(std::move(tin)) {}
  pseudo_copy(pseudo_copy const&) = delete;
};

template <class T>
pseudo_copy<T const&> pseudo(T& t) { return {t}; }

template <class T>
pseudo_copy<T&&> pseudo(T&& t) { return {t}; }

struct strange {
  strange(strange const&)=delete;
  strange(pseudo_copy<strange const&>) {} // copy ctor
  strange(pseudo_copy<strange&&>) {} // move ctor
  strange() = default;
};
Run Code Online (Sandbox Code Playgroud)

现在我们可以:

strange foo() { return pseudo(strange{}); }

strange x = pseudo(foo());
Run Code Online (Sandbox Code Playgroud)

现在,每次尝试复制strange 都必须调用pseudo,并且使用auto永远不合法,因为没有任何东西具有复制构造函数。

您还可以将复制构造函数设为私有,并使用它来实现pseudo复制构造函数。


请注意,复制/移动向量的含义受到 C++ 中省略规则的限制。


在 C++17 模板类类型推导中可以得出:

template <class T>
struct value{
  value_type_of<T> v;
  value(T in): v(std::forward<T>(in)) {}
};

int x = 3;
value a = std::ref( x );
Run Code Online (Sandbox Code Playgroud)

并且a.v将是一个int.

  • @alfc 如果您接受包装器,则 C++17 中的模板构造函数类型推导可能会有所帮助。所以 `value a=b;` 其中 `value&lt;T&gt;` 是一个模板,它将值存储在其自身的字段中。 (2认同)