vendredi 12 juillet 2019

Checking type with template C++

I'm studying the implementation of the Matrix class (explained in Stroustrup's book TC++PL 4th ed.), but I can't really understand some passages.

I found this code:

file traits.h -> https://github.com/statslabs/matrix/blob/master/include/slab/matrix/traits.h

file matrix.h -> https://github.com/statslabs/matrix/blob/master/include/slab/matrix/matrix.h

In matrix.h there is a function (as many other) with Enable_if:

template<typename T, std::size_t N>
template<typename M, typename F>
Enable_if<Matrix_type<M>(), Matrix<T, N> &> Matrix<T, N>::apply(const M &m, F f) {
    /// Some code...
}

and I think Enable_if says: If (M is a Matrix), declare the apply's return type as Matrix&.

Then, I want to know how does Matrix_type() works, so I go to traits.h, and I read:

struct substitution_failure {};

template <typename T>
struct substitution_succeeded : std::true_type {};

template <>
struct substitution_succeeded<substitution_failure> : std::false_type {};

template <typename M>
struct get_matrix_type_result {
  template <typename T, size_t N, typename = Enable_if<(N >= 1)>>
  static bool check(const Matrix<T, N> &m);

  template <typename T, size_t N, typename = Enable_if<(N >= 1)>>
  static bool check(const MatrixRef<T, N> &m);

  static substitution_failure check(...);

  using type = decltype(check(std::declval<M>()));
};

template <typename T>
struct has_matrix_type
    : substitution_succeeded<typename get_matrix_type_result<T>::type> {};

template <typename M>
constexpr bool Has_matrix_type() {
  return has_matrix_type<M>::value;
}

template <typename M>
using Matrix_type_result = typename get_matrix_type_result<M>::type;

template <typename M>
constexpr bool Matrix_type() {
  return Has_matrix_type<M>();
}

The first 3 structs describe success and failure cases, the template<> is the specialization of substitution_succeeded that says: if the type of substitution_succeeded is substitution_failure, "return" false else "return" true. I hope that what I'm saying is correct.

Now, get_matrix_type_result is completely obscure. I can't understand why it use a variadic function (check(...)), what are declval and decltype doing in this code and how it is possible that check can return a bool or a "substitution_failure". Why not just bool?

Thanks.

Aucun commentaire:

Enregistrer un commentaire