4

我有一个这样的模板类:

template <unsigned N>
class Pixel {
    float color[N];
}

我希望有一个带有精确N参数的构造函数来初始化类中的数组,如下所示:

Pixel<N> (float x_1, float x_2, ..., float x_N) {
    color[0] = x_1;
    color[1] = x_2;
    ...
}

显然我不能为 each 手动实现构造函数N。那么如何通过模板元编程或任何其他技术来实现这个目标呢?

4

3 回答 3

9

其他答案很好也很实用,但这个问题很有趣,做类似事情背后的技术可以为类似但更复杂和/或实际的问题和解决方案奠定良好的基础。这是按照您描述的方式计算构造函数参数的内容:

template <unsigned int N>
class Pixel {
public:
    template<typename... Floats> //can't use float... anyway
    Pixel(Floats&&... floats) : color{std::forward<Floats>(floats)...} {
        static_assert(sizeof...(Floats) == N, "You must provide N arguments.");
    }

private:
    float color[N];
};

int main() {
    Pixel<3> p(3.4f, 5.6f, 8.f);   
    Pixel<3> p2(1.2f); //static_assert fired
}
于 2013-07-12T03:44:43.290 回答
2

我会像这样使用 std::array :

#include <array>
#include <iostream>

template<unsigned int N>
class Pixel
{
public:
    Pixel(std::array<float, N> values)
    {
        for(size_t i=0; i<N; i++)
        {
            colors[i] = values[i];
        }
    }

private:
    float colors[N];
};

int main(int argc, char* argv[])
{
    std::array<float, 5> array = { 0.0f, 1.1f, 2.2f, 3.3f, 4.4f };
    Pixel<5> p(array);

    return 0;
}

我用了浮点颜色[N]; 作为成员变量,因为这就是你所拥有的,但如果由我决定,我只会存储数组本身。如果您无法访问 c++11 编译器,则可能有一种方法可以使用 boost::tuple 获得类似的结果(克里斯告诉我 std::tuple 也是 c++11,哎呀)。

于 2013-07-12T03:42:26.143 回答
2

这里很大程度上取决于你从哪里开始(C++03 与 C++11)以及你真正想去哪里(只传递数字,或者传递类似 an 的东西对你有用std::array)。

如果您有 C++11 并且只想传递数字,那么执行以下操作可能最简单:

#include <vector>
#include <iostream>
#include <initializer_list>

class pixel {
    std::vector<double> color;
public:
    pixel(std::initializer_list<double> && l) : color(l) {}
    ~pixel() {
        // show the data we received:
        for (double const &f : color)
            std::cout << f << "\t";
    }
};

int main() {
    pixel{1.9, 2.8, 3.7, 4.6, 5.5};
}

请注意,anstd::initializer_list不支持缩小转换,因此如果要将数字存储为float而不是double,则需要实际传递floats:

pixel{1.9f, 2.8f, 3.7f, 4.6f, 5.5f};

然而,与@Chris 的解决方案不同,这并不试图强制传递给定数量的参数——它只是符合存储您传递的任何数字。作为回报,它更容易使用。您不需要指定大小 - 它会根据您传递的项目数量来计算。

如果您喜欢这个总体思路,但坚持使用数组和 C++03(为什么?),您可以执行以下操作:

#include <vector>
#include <iostream>
#include <algorithm>

template<class T, size_t N>
class pixel {
    T color[N];
public:
    pixel(T(&matrix)[N]) {
        std::copy_n(matrix, N, color);
    }
};

template <class T, size_t N>
pixel<T, N> make_pixel(T(&matrix)[N]) {
    return pixel<T, N>(matrix);
}

int main() {
    float a [] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
    pixel<float, 5> p = make_pixel(a);
    return 0;
}

在这种情况下,我float作为模板参数传递,但如果你确定它总是float,你可以只传递大小,并使用float而不是T.

于 2013-07-12T04:41:28.850 回答