Я изучаю книгу Страустроупа "Программирование на С++, 4-е издание". И я пытаюсь следовать его примеру в матричном дизайне.
Его матричный класс сильно зависит от шаблонов, и я изо всех сил стараюсь в них разобраться. Вот один из вспомогательных классов для этой матрицы
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
- Почему у нас есть присвоение ('=') для имени типа
- Что мы получаем в итоге?
Обновление: код можно посмотреть в той же книге, на которую я ссылаюсь здесь Язык программирования C++, 4-е издание на стр. 841 (Matrix Design)
Enable_if<All(Convertible<Dims,size_t>()...)>
вызовет ошибку компилятора, поскольку аргумент шаблона может быть только выражением, известным во время компиляции. Возвращаемое значениеAll
не является. - person SergeyA   schedule 08.01.2016constexpr
перед определениями функций. Я почти уверен, что это заставит его работать. - person SirGuy   schedule 08.01.2016Enable_If
? Это на самом деле не относится к первому комментарию, поэтому я не уверен, чему вы подмигиваете... ;) - person SirGuy   schedule 08.01.2016