gpt4 book ai didi

c++ - 需要帮助来理解具有复杂类型名参数的模板函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:28:38 24 4
gpt4 key购买 nike

我正在研究 Stroustroup 的书“C++ Programming 4th edition”。我正在尝试效仿他在矩阵设计方面的例子。

他的矩阵类在很大程度上依赖于模板,我尽力弄清楚它们。这是该矩阵的辅助类之一

A Matrix_slice is the part of the Matrix implementation that maps a set of subscripts to the location of an element. It uses the idea of generalized slices (§40.5.6):

template<size_t N>
struct Matrix_slice {
Matrix_slice() = default; // an empty matrix: no elements
Matrix_slice(size_t s, initializer_list<size_t> exts); // extents
Matrix_slice(size_t s, initializer_list<size_t> exts, initializer_list<siz e_t> strs);// extents and strides
template<typename... Dims> // N extents
Matrix_slice(Dims... dims);


template<typename... Dims,
typename = Enable_if<All(Convertible<Dims,size_t>()...)>>
size_t operator()(Dims... dims) const; // calculate index from a set of subscripts

size_t size; // total number of elements
size_t start; // star ting offset
array<size_t,N> extents; // number of elements in each dimension
array<size_t,N> strides; // offsets between elements in each dimension
};
I

以下是构成我的问题主题的几行:

template<typename... Dims,
typename = Enable_if<All(Convertible<Dims,size_t>()...)>>
size_t operator()(Dims... dims) const; // calculate index from a set of subscripts

在本书的前面,他描述了如何实现 Enable_if 和 A​​ll():

template<bool B,typename T>
using Enable_if = typename std::enable_if<B, T>::type;


constexpr bool All(){
return true;
}
template<typename...Args>
constexpr bool All(bool b, Args... args)
{
return b && All(args...);
}

我有足够的信息来了解它们是如何工作的,通过查看他的 Enable_if 实现我也可以推断出 Convertible 函数:

template<typename From,typename To>
bool Convertible(){
//I think that it looks like that, but I haven't found
//this one in the book, so I might be wrong
return std::is_convertible<From, To>::value;
}

所以,我可以理解这个模板函数声明的构建 block 但是当我试图理解它们是如何工作的时候我很困惑。希望对你有帮助

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;

问题是:

  1. 我们不需要 Enable_if 的第二个模板参数
  2. 为什么我们要为类型名赋值('=')
  3. 我们最终会得到什么?

更新:您可以在我在这里引用的同一本书中查看代码 The C++ Programming Language 4th edition在第 841 页(矩阵设计)

最佳答案

这是基本的 SFINAE。可以往上看here ,例如。

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

  1. @GuyGreer 的回答中提到,第二个模板参数默认为void。 .

  2. 代码可以看成是“正常”的函数模板定义

    template<typename ...Dims, typename some_unused_type = enable_if_t<true> >
    size_t operator()(Dims... dims) const;

    随着 = , 参数 some_unused_type默认为右侧的类型。并且因为不使用类型 some_unused_type明确地,也不需要给它一个名字,只需将其留空即可。

    这是 C++ 中常见的方法,也适用于函数参数。例如检查 operator++(int) -- 一个不写operator++(int i)或类似的东西。

  3. 一起发生的是 SFINAE,它是 Substitution Failure Is Not An Error 的缩写。这里有两种情况:

    • 首先,如果 std::enable_if_t 的 bool 参数是false , 一个得到

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

      由于 typename = 的右侧没有有效类型, 类型推导失败。但是,由于 SFINAE,它不会导致编译时错误,而是会导致从重载集中删除该函数。

      实践的结果就像函数没有被定义一样。

    • 其次,如果 std::enable_if_t 的 bool 参数是true , 一个得到

      template<typename ...Dims, typename = void>
      size_t operator()(Dims... dims) const;

      现在typename = void是有效的类型定义,因此无需删除该函数。这样就可以正常使用了。

应用于您的示例,

template<typename... Dims,
typename = Enable_if<All(Convertible<Dims,size_t>()...)>>
size_t operator()(Dims... dims) const;

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

关于c++ - 需要帮助来理解具有复杂类型名参数的模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34678701/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com