Reference:
https://vsdmars.blogspot.com/2018/05/caccu2018-tricks-library-implementation.html
While reading {fmt} code:
https://github.com/fmtlib/fmt/blob/e6d478f8e88a357671c39bd39922ecac32aa2f58/include/fmt/core.h#L3107
template <typename... Args>
using format_string = basic_format_string<char, type_identity_t<Args>...>;
wondering why is type_identity_t needed?
This is due to how arguments participate function parameter deduction.
This is sort of template deduction 101, i.e. for parameters there's no implicit conversion involved.
Thus in order to avoid ambiguity from the deduction rule imposed on compiler,
introducing a Non-deduced contexts which uses the deduced type explicitly(which avoids implicit conversion at compile time) to remove ambiguity and allow implicit conversion at runtime.
e.g.
// the identity template, often used to exclude specific arguments from deduction
// (available as std::type_identity as of C++20)
template<typename T>
struct identity { typedef T type; };
template<typename T>
void bad(std::vector<T> x, T value = 1);
template<typename T>
void good(std::vector<T> x, typename identity<T>::type value = 1);
std::vector<std::complex<double>> x;
bad(x, 1.2); // P1 = std::vector<T>, A1 = std::vector<std::complex<double>>
// P1/A1: deduced T = std::complex<double>
// P2 = T, A2 = double
// P2/A2: deduced T = double
// error: deduction fails, T is ambiguous
good(x, 1.2); // P1 = std::vector<T>, A1 = std::vector<std::complex<double>>
// P1/A1: deduced T = std::complex<double>
// P2 = identity<T>::type, A2 = double
// P2/A2: uses T deduced by P1/A1 because T is to the left of :: in P2
// OK: T = std::complex<double>
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.