Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 需要帮助了解带有复杂typename参数的模板函数吗_C++_Metaprogramming_Variadic Templates_Variadic Functions_Enable If - Fatal编程技术网

C++ 需要帮助了解带有复杂typename参数的模板函数吗

C++ 需要帮助了解带有复杂typename参数的模板函数吗,c++,metaprogramming,variadic-templates,variadic-functions,enable-if,C++,Metaprogramming,Variadic Templates,Variadic Functions,Enable If,我正在看Stroustroup的一本书“C++编程第四版”。我正试着以他为榜样来设计矩阵 他的矩阵类很大程度上依赖于模板,我尽我最大的努力找出它们。 下面是这个矩阵的一个助手类 矩阵_切片是矩阵实现中映射 元素位置的下标集。它使用了这个想法 广义切片的数量(§40.5.6): 模板 结构矩阵{ 矩阵_slice()=default;//空矩阵:无元素 矩阵切片(大小、初始值设定项列表exts);//范围 矩阵_切片(大小、初始值设定项_列表exts、初始值设定项_列表strs);//范围和步长

我正在看Stroustroup的一本书“C++编程第四版”。我正试着以他为榜样来设计矩阵

他的矩阵类很大程度上依赖于模板,我尽我最大的努力找出它们。 下面是这个矩阵的一个助手类

矩阵_切片是矩阵实现中映射 元素位置的下标集。它使用了这个想法 广义切片的数量(§40.5.6):

模板
结构矩阵{
矩阵_slice()=default;//空矩阵:无元素
矩阵切片(大小、初始值设定项列表exts);//范围
矩阵_切片(大小、初始值设定项_列表exts、初始值设定项_列表strs);//范围和步长
模板//N扩展数据块
矩阵_切片(Dims…Dims);

模板尽管缺少
constepr
s,但它是一个包含两个参数的模板,但第二个参数默认为
void
。为保持该约定,为其编写一个快速别名是有意义的

因此,别名应定义为:

   template <bool b, class T = void>
   using Enable_if = typename std::enable_if<b, T>::type;
模板
使用Enable_if=typename std::Enable_if::type;
我不知道书中是否有这个默认参数,只是这会解决这个问题

类型的赋值称为a,并按照tin上的说明执行,当您引用别名时,实际上是指它的别名。在这种情况下,这意味着当您编写
Enable\u if
时,编译器会方便地将其扩展为
typename std::Enable\u if::type
,为您节省所有额外的键入


最终得到的函数只有在传递给它的每个参数都可转换为
std::size\t
时才可调用。这允许在不满足特定条件时忽略函数重载,这是一种比仅匹配类型以选择要调用的函数更强大的技术。
的链接>std::enable_,如果
有更多关于为什么要这样做的信息,但我警告初学者,这个主题会让人兴奋。

这是基本的SFINAE。例如,你可以阅读它

对于答案,我在这里使用的是
std::enable_if_t
,而不是书中给出的
EnableIf
,但两者是相同的:

  • 正如@guygrer在回答中提到的,的第二个模板参数默认为
    void

  • 该代码可以作为“普通”函数模板定义读取

    template<typename ...Dims, typename some_unused_type = enable_if_t<true> >
    size_t operator()(Dims... dims) const;
    
    由于
    typename=
    的rhs上没有有效的类型,因此类型推断失败。但是,由于SFINAE,它不会导致编译时错误,而是会从重载集中删除函数

    实践中的结果是,该函数似乎没有被定义

  • 其次,如果
    std::enable_if_t
    的布尔参数为
    true
    ,则

    template<typename ...Dims, typename = /* not a type */>
    size_t operator()(Dims ... dims) const;
    
    template<typename ...Dims, typename = void>
    size_t operator()(Dims... dims) const;
    

    上面的意思是,只有当
    All(Convertible()…
    true
    时,该函数才存在。这基本上意味着函数参数都应该是整数索引(我个人认为,我会用
    std::is_integral
    来写).

    这不可能是真正的代码。
    Enable\u if
    将触发编译器错误,因为模板参数只能是编译时已知的表达式。
    All
    的返回值不是。@SergeyA我想他只是在函数定义前面缺少了一个
    constepr
    。我很确定这会使它工作。@GuyGreer,OP可能。但OP还缺少什么呢?;)@SergeyA He缺少模板别名
    Enable_If
    ?的默认模板参数,但这与第一条评论并不相关,所以我不确定你在暗示什么…;)@GuyGreer,我试图说明一点,当代码不起作用时,我无法解释代码是如何工作的。我不会为OP校对这个问题。但是如果可以的话,请随意回答这个问题。谢谢,但在topicA的两个挑剔问题中,它仍然没有回答另外两个问题(如果你愿意,也可以随意挑剔我的答案:P),类型推断失败可能会导致编译错误,如果可以找到另一个函数重载代替它,则不会导致编译错误。此外,
    Convertible
    std::is_integral
    更通用,因为后者从预先确定的类型列表中检查出现的情况,而前者将接受带有c的用户定义类型onversion到
    std::size\t
    (我很确定转换到任何整数类型就足够了,因为在那之后,类型升级就完成了,而不是转换到
    std::size\t
    )。这是一个很好的解释。非常感谢。
    template<typename... Dims,
    //so here we accept the fact that we can have multiple arguments like (1,2,3,4)
    
            typename = Enable_if<All(Convertible<Dims,size_t>()...)>>
            //Evaluating and expanding from inside out my guess will be
            //for example if Dims = 1,2,3,4,5
            //Convertible<Dims,size_t>()... = Convertible<1,2,3,4,5,size_t>() =
            //= Convertible<typeof(1),size_t>(),Convertible<typeof(2),size_t>(),Convertible<typeof(3),size_t>(),...
            //= true,true,true,true,true
    
            //All() is thus expanded to All(true,true,true,true,true)            
            //=true;
    
            //Enable_if<true>
            //here is point of confusion. Enable_if takes two tamplate arguments, 
            //Enable_if<bool B,typename T>
            //but here it only takes bool
    
            //typename = Enable_if(...) this one is also confusing
    
            size_t operator()(Dims... dims) const; // calculate index from a set of    subscripts
    
    template<typename ...Dims,typename = Enable_if<true>>
    size_t operator()(Dims... dims) const;
    
       template <bool b, class T = void>
       using Enable_if = typename std::enable_if<b, T>::type;
    
    template<typename ...Dims, typename some_unused_type = enable_if_t<true> >
    size_t operator()(Dims... dims) const;
    
    template<typename ...Dims, typename = /* not a type */>
    size_t operator()(Dims ... dims) const;
    
    template<typename ...Dims, typename = void>
    size_t operator()(Dims... dims) const;
    
    template<typename... Dims,
            typename = Enable_if<All(Convertible<Dims,size_t>()...)>>
            size_t operator()(Dims... dims) const;