Стандартная библиотека предоставляет шаблоны для определения характеристик различных типов во время компиляции. Например:
std::is_integral<T>::value
сообщит вам, является ли что-то целым типом или нет.
Начиная с C ++ 17, для этих шаблонов признаков типа были добавлены ярлыки «вспомогательные шаблоны».
std::is_integral_v<T>
обеспечивает тот же результат, не требуя ::value
Подобно std::is_integral
, у меня есть довольно сложный шаблон, чтобы определить, является ли один тип специализацией другого:
template <typename T, template <typename...> typename Template>
struct is_specialization : std::false_type {};
template <template <typename...> typename Template, typename... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};
Пример использования показан ниже (Это позволит включить эту функцию шаблона, если переданный тип является специализацией std::complex
):
#include <complex>
#include <iostream>
#include <type_traits>
template <typename T>
struct MyComplex
{
MyComplex(const T& real, const T& imag)
: real(real)
, imag(imag)
{}
T real() { return this->real; }
T imag() { return this->imag; }
private:
T real;
T imag;
};
// Only enable this template if "T" is a specialization of "std::complex"
template <typename T,
typename = std::enable_if_t<is_specialization<T, std::complex>::value>
>
void foo(T value)
{
std::cout << value.real() << std::endl;
}
int main()
{
std::complex<double> value1{ 1.0, 2.0 };
foo(value1);
std::complex<int> value2{ 1, 2 };
foo(value2);
MyComplex<double> value3{ 1.0, 2.0 };
// Fails to compile because "MyComplex<double>" is not a specialization of "std::complex"
//foo(value3);
}
Я хотел бы написать вспомогательный шаблон "_v" для этого, но я не уверен, как, поскольку он включает в себя вложенные шаблоны.
Поскольку is_specialization
принимает два параметра шаблона, моей первой мыслью было просто сделать что-то подобное и, возможно, компилятор выяснит, что «T» и «U» могут быть вложенными типами сами по себе, но, похоже, он не работает:
template <typename T, typename U>
inline constexpr bool is_specialization_v = is_specialization<T, U>::value;
Как правильно написать «_v» вспомогательный шаблон для чего-то вроде это? Пожалуйста, попробуйте объяснить, как это работает в ответе, так как я довольно плохо знаком с шаблонным метапрограммированием и все еще борюсь с некоторыми концепциями.