【发布时间】:2016-11-15 13:06:49
【问题描述】:
在n4502 中,作者描述了封装void_t 技巧的检测习语的早期实现。这是它的定义以及为is_assignable 定义特征的用法(实际上是is_copy_assignable)
template<class...>
using void_t = void;
// primary template handles all types not supporting the operation:
template< class, template<class> class, class = void_t< > >
struct
detect : std::false_type { };
// specialization recognizes/validates only types supporting the archetype:
template< class T, template<class> class Op >
struct
detect< T, Op, void_t<Op<T>> > : std::true_type { };
// archetypal expression for assignment operation:
template< class T >
using
assign_t = decltype( std::declval<T&>() = std::declval<T const &>() );
// trait corresponding to that archetype:
template< class T >
using
is_assignable = detect<void, assign_t, T>;
他们提到他们不喜欢这个,因为 void 在 is_assignable 特征中使用:
虽然生成的代码比 原来,我们不喜欢上面的检测接口,因为
void元函数调用中的参数是一个实现细节, 不应泄露给客户端代码。
但是,void 首先对我没有任何意义。如果我尝试使用此类型特征来检测 int 是否可复制分配,我会得到 std::false_type Demo。
如果我将is_assignable 重写为:
template< class T >
using
is_assignable = detect<T, assign_t>;
这对我来说更有意义,然后该特征似乎可以正常工作: Demo
所以我的问题是我是否误解了本文档中的某些内容,或者只是一个错字?
如果它是一个错字,那么我不明白为什么作者觉得有必要讨论他们不喜欢void泄露的原因,这让我很确定我是只是错过了一些东西。
【问题讨论】:
-
N4502 的前身N4436 有更严重的拼写错误(模板参数的数量不正确)。所以另一组错别字是不可能的...... ;-]
-
不应该是
using is_assignable = detect<T, assign_t, void>吗? -
@Rerito 我不认为结尾的
void是必要的。正如 Ildjarn 所建议的那样,我认为造成混淆的根本原因是拼写错误。正如作者在论文脚注中提到的,也许这是一个“thinko” -
@Rerito:谢谢。你能想出一个需要
void的场景吗? -
这种情况下的尾随 void 是不必要的,因为默认模板参数是在非专用模板中指定的。
标签: c++ language-lawyer template-meta-programming c++17