Правильный способ написания вспомогательного шаблона "_v" в стиле C ++ 17 для вложенного шаблона - PullRequest
0 голосов
/ 30 января 2020

Стандартная библиотека предоставляет шаблоны для определения характеристик различных типов во время компиляции. Например:

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» вспомогательный шаблон для чего-то вроде это? Пожалуйста, попробуйте объяснить, как это работает в ответе, так как я довольно плохо знаком с шаблонным метапрограммированием и все еще борюсь с некоторыми концепциями.

1 Ответ

2 голосов
/ 30 января 2020

Ваш аргумент псевдонима неверен, он должен совпадать с основным шаблоном:

template <typename T, template <typename...> typename Template>
inline constexpr bool is_specialization_v = is_specialization<T, Template>::value;
...