更新:有人建议在某些情况下更改auto
的含义。
Implicit Evaluation of “auto” Variables and Arguments来自Joel Falcou和其他人。
隐式评估应:
- 启用类实现者以指示在auto语句中评估此类的对象;
- 启用它们以确定已评估对象的类型;
醇>...
C ++ 11的auto
关键字很棒。
但是,在我看来,如果某个类型是非常规(例如,参见What is a "Regular Type" in the context of move semantics?),则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>`.
(在现实生活中,这将是一个更复杂的课程,重点是手头的课程不规律。)
我发现auto r = rd
无法工作(给出编译错误)的唯一方法是使类不可复制,但是我需要类具有复制构造函数(具有特殊语义,但仍然是复制构造函数) )。
有没有办法以某种方式禁用语法auto r = rd
?当decltype(rd)
不规律时。
(更好的方法是能够以某种方式告诉编译器auto
应该做什么。)
注意:这不是一个非常人为的问题,可以看出这类问题是std::vector<bool>::reference
(它也是一个参考包装器)的核心。禁用(某种程度上)语法auto b = v[10]
不会解决std::vector<bool>
的问题,但会更难以使用。
我错过了什么吗?我应该改变设计的其他部分吗?非常规类是否具有可帮助编译器确定更一般的自动的类型特征(例如,对bool
auto b = v[10]
std::vector<bool> v
进行推导notifyDataSetChanged()
。)
答案 0 :(得分:3)
复制构造函数意味着您希望复制该类。 auto x = y;
会将y
复制到x
。
如果您想要一个不想自动运行的超级特殊副本,可以使用代理对象。
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;
};
现在我们可以:
strange foo() { return pseudo(strange{}); }
strange x = pseudo(foo());
现在,每次复制strange
的尝试都必须通过调用pseudo
,使用auto
从来都不合法,因为没有副本构造
您也可以将复制构造函数设为私有,并使用它来实现pseudo
复制构造函数。
请注意,复制/移动ctor的含义受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 );
而a.v
将是int
。