有没有办法禁用非常规类型的自动声明? [英] Is there a way to disable auto declaration for non regular types?
问题描述
UPDATE:建议在某些情况下更改 auto
的含义.
UPDATE: There is a proposal to change the meaning of auto
in certain situations.
自动"变量和参数的隐式评估,作者:Joel Falcou 和其他人.
Implicit Evaluation of "auto" Variables and Arguments by Joel Falcou and others.
隐式评估应:
- 使类实现者能够在 auto 语句中指示对此类的对象求值;
- 使他们能够确定被评估对象的类型;
...
<小时>
C++11 的 auto
关键字很棒.
但是在我看来,如果类型是不规则(例如,请参见 在移动语义的上下文中什么是常规类型"?)auto
的使用变得棘手.
However in my opinion if a type is Not Regular (see for example, What is a "Regular Type" in the context of move semantics?) the usage of auto
becomes tricky.
有没有办法禁用这种类型的 auto
声明?
Is there a way to disable the auto
declaration for such type?
假设有一个模拟引用的 ref
类
Suppose one has a ref
class that emulates a reference
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>`.
(在现实生活中它会是一个更复杂的类,重点是它手头的类不是正规的.)
(in real life it would be a more complicated class, the important point is that the class at hand it is not regular.)
我发现 auto r = rd
不起作用(给出编译错误)的唯一方法是使类不可复制,但是我需要该类具有复制构造函数(具有特殊语义,但仍然是一个复制构造函数).
The only way I found auto r = rd
not to work (give a compile error) is to make the class non copyable, however I need the class to have copy constructor (with a special semantics, but a copy constructor still).
有没有办法以某种方式禁用语法 auto r = rd
?当 decltype(rd)
不规则时.
Is there a way to disable a syntax auto r = rd
somehow? when decltype(rd)
is not regular.
(更好的是能够以某种方式告诉编译器 auto
应该准确做什么).
(Even better could be to be able somehow to tell the compiler what auto
should do precisely).
注意:这不是一个很人为的问题,可以看出这类问题是std::vector
(也是一个引用包装器)的核心).禁用(以某种方式)语法 auto b = v[10]
不会解决 std::vector
的问题,但它会使错误使用变得更加困难.
Note: This is not a very artificial problem, one could see that this type of problem is at the core of std::vector<bool>::reference
(which is also a reference wrapper). Disabling (somehow) the syntax auto b = v[10]
wouldn't solve the problem of std::vector<bool>
but it will make bad usage harder.
我错过了什么吗?我应该更改设计的其他部分吗?非常规类是否应该有一个类型特征来帮助编译器确定一个更通用的 auto(例如推导出 bool
for auto b = v[10]
where >std::vector
.)
Am I missing something? Should I change some other part of the design? Should the non-regular classes have a type trait that would help the compiler determine a more general auto (for example deduce bool
for auto b = v[10]
where std::vector<bool> v
.)
推荐答案
复制构造函数意味着您希望类被复制.auto x = y;
将 y
复制到 x
中.
A copy constructor means you expect the class to be copied. auto x = y;
does a copy of y
into x
.
如果你想要一个不想自动运行的超级特殊副本,你可以使用代理对象.
If you want a super-special copy that you don't want to be run automatically, you can use a proxy object.
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
永远不合法,因为没有任何东西有复制构造函数.
and now every attempt to copy strange
must go through a call to pseudo
, and use of auto
is never legal, because nothing has a copy constructor.
您也可以将复制构造函数设为私有,并使用它来实现伪
复制构造函数.
You could also make the copy constructor private, and use it to implement the pseudo
copy constructor.
请注意,复制/移动构造函数的含义受 C++ 中的省略规则约束.
Note that the meaning of copy/move ctor is constrained by elision rules in C++.
在 C++17 模板类中类型推导可以:
In C++17 template class type deduction could make:
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
.
这篇关于有没有办法禁用非常规类型的自动声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!