如何修复此类模板

时间:2016-10-26 15:56:56

标签: c++ templates

我正在尝试编写一个类,在最简单的示例中,其工作原理如下:

// Example program
#include <iostream>
#include <complex>
#include <typeinfo>

template<typename NumberType>
class SomeClass
{
    public:
        SomeClass(NumberType a_) : a(a_) {}
        void get_number() 
        {
            if (typeid(NumberType) == typeid(std::complex<double>))
                std::cout << a.real() << " " << a.imag() << std::endl;
            else
                std::cout << a << std::endl;
        }
    private:
        NumberType a;
};

int main()
{
    int a=1;
    std::complex<double> c(2.0,3);

    SomeClass<int> A(a);    
    A.get_number();

    SomeClass<std::complex<double>> C(c);
    C.get_number();

    return 0;
}

它基本上打印任何实数,但它应该将复数分成两个实数。

如果我按照显示的方式编译它,错误信息如下

 In instantiation of 'void SomeClass<NumberType>::get_number() [with NumberType = int]':
28:18:   required from here
14:46: error: request for member 'imag' in '((SomeClass<int>*)this)->SomeClass<int>::a', which is of non-class type 'int'
14:27: error: request for member 'real' in '((SomeClass<int>*)this)->SomeClass<int>::a', which is of non-class type 'int'

我理解,由于a在第一种情况下的类型为int,因此我无法在其上使用imag(),因此会显示错误消息。

如何修改此类,以便在任意NumberType模板参数的情况下执行我所需的操作?

2 个答案:

答案 0 :(得分:2)

你应该使用模板和模板专门化,而不是typeid - 在C ++中你想要使用编译时抽象,而不是根据变量或值的类型做出运行时决定。

您可以拥有以下独立的助手功能:

// General case:
template <typename T>
void get_number(const T& value)
{
    std::cout << value << std::endl;
}

// Specialization for complex<double>
template <>
void get_number<std::complex<double> >(const std::complex<double>& value)
{
    std::cout << value.real() << " " << value.imag() << std::endl;
}

// ... More specializations if you need to.

现在你可以致电:

get_number(3);
get_number(std::complex<double>(1, 2));

为了使其更通用,您可以使用std::complex<T>代替std::complex<double>。这需要更多的工作,因为不支持功能模板部分特化。您需要使get_number成为helper结构的静态成员,如下所示:

// General case:
template <typename T>
struct get_number_helper {
    static void get(const T& value)
    {
        std::cout << value << std::endl;
    }
 };

// Specialization for complex<T>
template <typename T>
struct get_number_helper<std::complex<T> > {
    static void get(const std::complex<T>& value)
    {
        std::cout << value.real() << " " << value.imag() << std::endl;
    }
};

template<typename T>
void get_number(const T& value)
{
    get_number_helper<T>::get(value);
}

答案 1 :(得分:2)

正如alexc已经提到的那样,当你使用std::complex<>::real或{{1}时,你应该使用模板规范来阻止编译器 imagint成员作为数据类型。

会员模板规格更接近您现有的规格:

double