【发布时间】:2016-01-08 13:52:59
【问题描述】:
我正在研究 Stroustroup 的书“C++ Programming 4th edition”。我正在尝试效仿他的矩阵设计示例。
他的矩阵类在很大程度上依赖于模板,我尽力弄清楚它们。 这是此矩阵的辅助类之一
Matrix_slice 是 Matrix 实现的一部分,它映射一个 元素位置的一组下标。它使用了这个想法 广义切片(§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 和 All() 是如何实现的:
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;
}
所以,我可以理解这个模板函数声明的构建块 但是当我试图理解它们是如何工作的时候我很困惑。 希望能帮到你
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;
问题是:
- 我们不需要 Enable_if 的第二个模板参数吗
- 为什么我们要为类型名赋值 ('=')
- 我们最终会得到什么?
更新: 您可以在我在这里引用的同一本书中查看代码 The C++ Programming Language 4th edition 第 841 页(矩阵设计)
【问题讨论】:
-
这不是真正的代码。
Enable_if<All(Convertible<Dims,size_t>()...)>将触发编译器错误,因为模板参数只能是编译时已知的表达式。All的返回值不是。 -
@SergeyA 我认为他只是在函数定义前面缺少
constexpr。我很确定这会成功。 -
@GuyGreer,OP 可能。但除了 OP 还缺少什么? ;)
-
@SergeyA 他缺少模板别名
Enable_If的默认模板参数?不过,这与第一条评论并没有真正的关系,所以我不确定你在眨眼什么……;) -
@GuyGreer,我试图指出我无法解释代码在不工作时是如何工作的。我不会为 OP 校对这个问题。但如果可以,请随时回答这个问题。
标签: c++ metaprogramming variadic-templates variadic-functions enable-if