使用数组参数C ++定义模板化类的成员函数

时间:2014-05-09 20:46:53

标签: c++ arrays templates

考虑我有一个类模板,它以数组作为参数:

template <int N, const float numbers[N]>
class TemplateClass
{
public:
    TemplateClass()
    {
        for (int i = 0; i < N; i++)
        {
            cout << numbers[i] << endl;
        }
    }
};

我可以像这样成功使用它:

const int N = 3;
extern const float Constants[N];
const float Constants[N] = { 2.0f, 2.1f, 2.2f };

int main()
{
    TemplateClass<3, Constants>();
    return 0;
}

但是,我尝试将构造函数方法体移到类声明之外是徒劳的:

// Fails with: 
// error C2440: 'specialization' : cannot convert from 'const float *' to 'const float [3]'
template <int N, const float numbers[N]>
TemplateClass<N, numbers>::TemplateClass()
{
    for (int i = 0; i < N; i++)
    {
        cout << numbers[i] << endl;
    }
}



// Fails with:
// error C3860: template argument list following class template name must list parameters in the order used in template parameter list
// error C3855: 'TemplateClass<N,numbers>': template parameter 'numbers' is incompatible with the declaration
template <int N, const float* numbers>
TemplateClass<N, numbers>::TemplateClass()
{
    for (int i = 0; i < N; i++)
    {
        cout << numbers[i] << endl;
    }
}

这在VC ++ 11和VC ++ 12编译器上都可以看到。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

原因/错误:

根据标准§14.1/ 4,非类型模板参数必须具有以下类型之一:

  1. 积分或枚举类型,
  2. 指向对象或指向函数的指针,
  3. lvalue引用对象或lvalue对函数的引用,
  4. 指向成员的指针,
  5. std::nullptr_t
  6. const float numbers[N]不属于上述情况。另见(https://stackoverflow.com/a/16214727/2352671

    现在仍然存在的问题是为什么当您在线定义构造函数(即,在类的定义中)时,您的程序编译并运行正常。

    这个问题的答案是 Non-type template parameters that are declared as arrays or functions are converted to pointers or pointers to functions, respectively. 我们可以通过打印类型来确认 在内联构造函数中的numbers

    template <int N, const float numbers[N]>
    class TemplateClass
    {
    public:
        TemplateClass()
        {
            std::cout << typeid(numbers).name() << std::endl;
            for (int i = 0; i < N; i++)
            {
                std::cout << numbers[i] << std::endl;
            }
        }
    };
    

    我们得到的输出是:

      
        

    float const *

      

    因此,标准不会受到侵犯,代码也会起作用。

    我们要回答的下一个问题是,当您使用参数模板列表template <int N, const float *numbers>定义类定义之外的构造函数时 你得到一个编译错误。

    这个问题的答案是因为您的类定义中的参数列表(即template <int N, const float numbers[N]>)和构造定义中的参数列表不匹配。

    解决方案:

    #include <iostream>
    
    using namespace std;
    
    template <int N, const float* numbers>
    class TemplateClass
    {
    public:
        TemplateClass();
    };
    
    template <int N, const float *numbers>
    TemplateClass<N, numbers>::TemplateClass()
    {
        for (int i = 0; i < N; i++)
        {
            cout << numbers[i] << endl;
        }
    }
    
    const int N = 3;
    extern const float Constants[N];
    const float Constants[3] = { 2.0f, 2.1f, 2.2f };
    
    int main()
    {
        TemplateClass<3, Constants>();
        return 0;
    }
    

    输出:

    2

    2.1

    2.2

答案 1 :(得分:-1)

模板方法必须在模板类的同一文件头中定义。模板只是一个声明,当您将它用于变量时,它会被编译器实例化,因此模板方法无法在cpp文件中实现。