Шаблонное определение типа
Если вы не хотите иметь специализацию, вы можете просто использовать шаблонный typedef, например, так:
template <typename T>
using ComplexVector = Vector<std::complex<T>>;
Пользователи могут затем использовать ComplexVector<float>
, и он будет правильно представлять Vector<std::complex<T>>
.
Это очень простое решение, которое не совсем соответствует вашим потребностям. Посмотрите на следующие решения для вашей конкретной проблемы.
Шаблонное наследование
Если ваша цель состоит в том, чтобы изменять только определенные методы, когда T
равен std::complex<U>
, вы должны наследовать от Vector
следующим образом:
template <typename T>
class Vector
{
public:
bool is_complex() { return false; }
};
template <typename U>
class ComplexVector : Vector<std::complex<U>>
{
public:
bool is_complex() { return true; }
};
Это также позволяет добавлять методы, доступные только для векторов на основе complex
.
Добавление метода только для ComplexVector
Если вы хотите иметь возможность «улучшать» ComplexVector
, вы можете сделать это так:
#include <iostream>
#include <complex>
template <typename T>
class Vector
{
public:
bool is_complex() { return false; }
};
template <typename U>
class ComplexVector : Vector<std::complex<U>>
{
public:
bool is_complex() { return true; }
bool only_for_complex() { return true; } // Only in ComplexVector
};
int main() {
Vector<float> float_vec;
ComplexVector<float> complex_vec;
std::cout << "Is float_vec complex? " << float_vec.is_complex() << "\n";
std::cout << "Is complex_vec complex? " << complex_vec.is_complex() << "\n";
// The following line doesn't compile
// std::cout << "Is only_for_complex method in float_vec? " << float_vec.only_for_complex() << "\n";
std::cout << "Is only_for_complex method in complex_vec? " << complex_vec.only_for_complex() << "\n";
return 0;
}
Рабочая демонстрация здесь
Использование черты типа small для проверки типа
Используя некоторые шаблоны, мы можем создать небольшого помощника, чтобы определить, является ли данный тип ComplexVector
или нет. Это может пригодиться, если вы хотите безопасно вызывать определенные методы в насыщенной среде шаблона:
// For any type T, value is false.
template <typename T>
struct is_complex_vector
{
static const bool value = false;
};
// We specialize the struct so that, for any type U,
// passing ComplexVector<U> makes value true
template <>
template <typename U>
struct is_complex_vector<ComplexVector<U>>
{
static const bool value = true;
};
is_complex_vector<typeof(float_vec)>::value; // is false
is_complex_vector<typeof(complex_vec)>::value; // is true
Вот еще одна небольшая демонстрация, демонстрирующая это поведение на практике
value
будет определено при компиляции. Это может позволить вам использовать некоторые трюки SFINAE , чтобы лучше контролировать поток вашей программы. (Или вы можете использовать constexpr, если , если вы используете C ++ 17 .)