与维度无关的类使用可变参数模板

时间:2013-12-09 08:32:29

标签: c++ c++11 variadic-templates

我有一个模拟二维和三维工程问题的科学库。 2D和3D代码非常相似,但专门针对2D和3D问题进行手写。例如,一个简单的point类在2D和3D中明确地具有单独的实现。

我对c++11很新,但根据我读过的内容,我决定测试新功能,将这些代码无缝地组合成一个与维度无关的框架。我的第一次尝试是编写一个简单的通用point类,如下所示:

#include <iostream>

template<unsigned short dim, typename T=double>
class point{
    const T x[dim]; 

public:
    template<typename... X>
    point(X... xs): x{xs...} 
    {
        static_assert(dim>0, "A point needs to at least have one component");
    }

    friend std::ostream& operator<<(std::ostream& os, const point<dim,T>& p)
    {
        os << "(";
        for (unsigned short i=0; i<dim-1; i++)
            os << p.x[i] << ", ";
        os << p.x[dim-1] << ")" << std::endl;

        return os;
    }
};

int main(){
    point<3> p = {3., 4.};
    std::cout << p;
    return 0;
}

除了我有两个问题/问题外,它的工作正常。首先,为什么我需要模板参数TX?为什么我不能告诉编译器为variardic构造函数使用相同的模板参数?对我来说,这似乎是一个合理的要求!

其次,如果我尝试point<2> p = {3, 5};,我会被narrowing conversion of ‘xs#0’ from ‘int’ to ‘const double’ inside { } [-fpermissive]大吼一声。为什么我不能从整数初始化一个double?我从没想过这是非法的。这是c++11的新内容,如果是,那么这里的解决方法是什么?

2 个答案:

答案 0 :(得分:0)

您可以使用std::initializer_list并使用std::vector代替数组:

template<unsigned short dim, typename T=double>
class point{
    static_assert(dim>0, "A point needs to at least have one component");
    const std::vector<T> x;

public:
    point(std::initializer_list<T> xs): x{xs} 
    {}

    ...
};

答案 1 :(得分:0)

我能够通过强制编译器将输入强制转换回T来解决问题:

template<unsigned short dim, typename T=double>
class point{
    static_assert(dim>0, "A point needs to at least have one component");
    const T x[dim]; 

public:
    template<typename... X>
    point(X... xs): x{static_cast<T>(xs)...} {}        
};

虽然这很尴尬,但我不明白标准中这种变化背后的理由,这可能对某人有用!