当前位置: 首页 > 知识库问答 >
问题:

'void_t'是如何工作的

寿亦
2023-03-14

我观看了Walter Brown在Cppcon14上关于现代模板编程的演讲(第一部分,第二部分),他介绍了他的void_tSFINAE技术。

示例:
给定一个简单的变量模板,如果所有模板参数都格式良好,则计算结果为void:

template< class ... > using void_t = void;
template< class , class = void >
struct has_member : std::false_type
{ };

// specialized as has_member< T , void > or discarded (sfinae)
template< class T >
struct has_member< T , void_t< decltype( T::member ) > > : std::true_type
{ };
class A {
public:
    int member;
};

class B {
};

static_assert( has_member< A >::value , "A" );
static_assert( has_member< B >::value , "B" );
  • has_member >
    • A::member存在
    • decltype(a::member)格式良好
    • void_t<>有效,并计算为void

    2.has_member

    • has_member >
      • B::member不存在
      • decltype(B::member)格式错误,以静默方式失败(sfinae)
      • has_member ,因此丢弃此模板

共有1个答案

隗翰海
2023-03-14

编写has_member::value时,编译器查找名称has_member并找到主类模板,即以下声明:

template< class , class = void >
struct has_member;

(在OP中,这是作为定义编写的。)

将模板参数列表与此主模板的模板参数列表进行比较。由于主模板有两个参数,但您只提供了一个,因此剩下的参数默认为默认模板参数:void。就像您编写了has_member ::value 一样。

template< class T >
struct has_member< T , void_t< decltype( T::member ) > > : true_type
{ };

在第二个模式void_t 中,模板参数t出现在无法从任何模板参数导出的上下文中。

这有两个原因:

>

  • decltype中的表达式被显式排除在模板参数推导之外。我猜这是因为它可以任意复杂。

    template<>
    struct has_member< A, void_t< decltype( A::member ) > > : true_type
    { };
    
    template<>
    struct has_member<A, void> : true_type
    { };
    

    现在,我们可以将此专门化的模板参数列表与提供给原始has_member::value的模板参数进行比较。这两种类型完全匹配,因此选择了这个部分专门化。

    另一方面,当我们将模板定义为:

    template< class , class = int > // <-- int here instead of void
    struct has_member : false_type
    { };
    
    template< class T >
    struct has_member< T , void_t< decltype( T::member ) > > : true_type
    { };
    

    我们最终得到了同样的专业化:

    template<>
    struct has_member<A, void> : true_type
    { };
    

    但这并不仅仅意味着部分特化的所有模板参数都必须推导出来;这也意味着替代必须成功并且(看起来?)模板参数必须与部分专门化的(替换的)模板参数匹配。请注意,我不完全知道标准在哪里指定了替换参数列表和提供的参数列表之间的比较。

  •  类似资料:
    • 应用程序具有上下文路径-->/spring-form-simple-project 因此,为了访问,我使用: 这个控制器又返回student.jsp,当提交这个student.jsp时,它用-->@RequestMapping(value=“/AddStudent”,method=RequestMethod.post)调用controller 任何关于这通常如何工作的指示都将是有帮助的。 谢谢!

    • 本文向大家介绍hibernate 是如何工作的?相关面试题,主要包含被问及hibernate 是如何工作的?时的应答技巧和注意事项,需要的朋友参考一下 读取并解析配置文件。 读取并解析映射文件,创建 SessionFactory。 打开 Session。 创建事务。 进行持久化操作。 提交事务。 关闭 Session。 关闭 SessionFactory。

    • 我很想知道谷歌应用商店服务中的Activity认可是如何工作的? 我认为活动是通过加速计数据识别的。是这样吗?。请告诉我详细情况如何

    • 我对GridBagLayout这一主题不熟悉,我无法理解约束、重量和填充之间的确切区别。 我可以而不分配。 除非您指定了至少一个非零值,否则所有组件都会聚集在其容器的中心。这是因为当权重为0.0(默认值)时,GridBagLayout会在其单元格网格和容器边缘之间放置任何额外的空间。 我的问题是,如果这是真的,那么为什么组件之间没有空间,它们看起来是连接的?

    • 从@mock和@injectmocks之间的差异,我理解@injectmocks被用作创建实例的注释,并将用@mock创建的mock注入其中。我想我不明白它是怎么工作的。 以下是我的问题: 在中,当我调用时,它返回一个空集...我的问题是:为什么不抛出(只声明mockedappoinceptions)?也许因为这是一个嘲弄?如果原因是这样,为什么模拟不抛出“NullPointerException

    • 这可能是一个很难回答的问题。我才刚开始学Java 我不懂paintComponent方法的操作。我知道如果我想画一些东西,我必须重写paintComponent方法。