C++ 有没有办法禁用非常规类型的自动声明?
更新:有人建议在某些情况下更改C++ 有没有办法禁用非常规类型的自动声明?,c++,c++11,auto,regular-type,C++,C++11,Auto,Regular Type,更新:有人建议在某些情况下更改auto的含义 乔尔·法尔库和其他人的作品 隐性评价应: 使类实现者能够指示在auto语句中计算此类的对象 使他们能够确定评估对象的类型 C++11的auto关键字很棒 然而,在我看来,如果一个类型是不规则的(例如,请参阅),那么auto的使用就会变得棘手 有没有办法禁用此类类型的auto声明 假设有一个模拟引用的ref类 double 5.; ref<double> rd = d; // `ref` behaves like a reference
auto
的含义
乔尔·法尔库和其他人的作品
隐性评价应:
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>`.
double 5。;
ref rd=d;//`ref`的行为类似于引用,因此它不是常规类型
参考rd2=rd;//`ref`可以(语法上)复制构造(由于其他原因,它不是规则的)
自动r=rd;//现在r不是double,但最糟糕的是ref。
(在现实生活中,这将是一个更为复杂的类,重要的一点是,当前的类并不规则。)
我发现auto r=rd
不起作用的唯一方法(给出一个编译错误)是使该类不可复制,但是我需要该类具有复制构造函数(具有特殊语义,但仍然是一个复制构造函数)
是否有办法以某种方式禁用语法auto r=rd
?当decltype(rd)
不规则时。
(更好的是能够以某种方式告诉编译器auto
应该精确地执行什么操作)
注意:这不是一个非常人为的问题,可以看出这类问题是std::vector::reference
(它也是一个参考包装器)的核心。禁用语法auto b=v[10]
并不能解决std::vector
的问题,但它会使糟糕的使用更加困难
我错过什么了吗?我应该改变设计的其他部分吗?如果非规则类有一个类型特征可以帮助编译器确定一个更通用的auto(例如,为
auto b=v[10]
推断bool
,其中std::vector v
)一个复制构造函数意味着您希望复制该类<代码>自动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;
};
现在,每一次复制奇怪的
的尝试都必须通过调用伪
,并且使用自动
从来都是不合法的,因为没有任何东西有复制构造函数
您还可以将复制构造函数设置为私有,并使用它实现伪
复制构造函数
注意,拷贝/移动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 );
模板
结构值{
v的值类型;
值(T in):v(std::forward(in)){
};
int x=3;
值a=标准::参考(x);
而
a.v
将是一个int
是否在分配可能性的位置添加了一个static\u assert
?这是否有帮助,分配不是问题,我可以在操作符=
中实现我需要的语义,甚至删除它。问题是允许这种auto r=rd
语法,并且允许它具有错误的含义(在C++中似乎不可能更改)。行auto r=rd
不是赋值,而是带有(错误)类型推断的构造。(更具体地说,对于“类引用类型”,它是(或应该是)绑定操作)。根据,您可以通过调用ref.get()
来访问您的值。从这个角度来看,构造应该是明确的。如果C++有一些特性,避免在类型上让你自己开枪,那不是很好吗?但是如果我们愿意的话,禁用有符号和无符号类型之间的隐式转换的能力在我的列表中会高得多……不,没有办法禁用这个核心语言特性。直到有人写了一个连贯的提案,并把所有的工作纳入下一个C++标准。code>auto被定义为做一件非常具体的事情,这件事与模板参数推导中发生的事情完全相同。如果您建议在某些情况下禁用auto
,出于一致性的考虑,您可能还应该在这些情况下禁用模板参数推断。好吧,我不同意,copy-constructible应该意味着至少这是有效的decltype(y)x=y
是有效的,并且有一定的意义auto x=y
在语义上是不同的,因为在泛型代码中,人们期望x
具有值语义,即使y
没有。我只是说auto
显然限制太多了。遗憾的是,对于真正的泛型代码,需要执行类似于::type x=y的typename value\u rep_代码>。其中,value\u rep
是一种特性(对于大多数情况,除了非常规类型外,这一特性微不足道)。@alfc如果您接受包装器,在C++17中可能会有关于模板构造函数类型推断的帮助。因此值a=b代码>其中value
是一个模板,它将一个值存储在其自身的字段中。好的,我必须研究一下这一点。这是非常有希望的,因为它隐藏/抽象了你的黑客行为。事实证明,对于C++14,我找到的解决方案是禁用移动和复制构造函数,这很有意义,迫使我使用auto&&
而不是auto
,但这没关系,因为至多一个没有复制或移动构造函数的类基本上是一个类似引用的类型。然而,该技术在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 );