简体   繁体   English

由模板参数固定的C ++函数参数数量

[英]C++ number of function's parameters fixed by template parameter

I have a template class like this: 我有一个像这样的模板类:

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

I hope to have a constructor with exact N parameters to initialize the array in the class, like this: 我希望有一个具有确切N参数的构造函数来初始化类中的数组,如下所示:

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

Obviously I can't implement the constructor by hand for each N . 显然,我无法为每个N手动实现构造函数。 So how can I achieve this goal by template metaprogramming or any other techniques? 那么如何通过模板元编程或任何其他技术来实现此目标?

The other answers are good and practical, but the question is interesting, and the technique behind doing something like that can form a good basis for similar, but more complicated and/or practical problems and solutions. 其他答案是好的且实用的,但是问题很有趣,并且执行类似操作的背后技术可以为类似但更复杂和/或更实际的问题和解决方案提供良好的基础。 Here's something that counts the constructor arguments the way you describe: 这是按照您描述的方式计算构造函数参数的内容:

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
}

I would make use of std::array like so: 我会像这样使用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;
}

I used float colors[N]; 我用了浮色[N]; as the member variable because that's what it seemed like you had, but if it were up to me I'd just store the array itself. 作为成员变量,因为这看起来就像您拥有的那样,但是如果由我决定,我将只存储数组本身。 If you don't have access to a c++11 compiler there may be a way to get a similar result using boost::tuple (chris informs me that std::tuple is also c++11, oops). 如果您无权使用c ++ 11编译器,则可以使用boost :: tuple获得类似的结果(克里斯告诉我std :: tuple也是c ++ 11,哎呀)。

A lot here depends on where you're starting from (C++03 vs. C++11) and where you really want to go (passing just numbers, or if passing something like an std::array works for you). 这里的很多内容取决于您从哪里开始(C ++ 03与C ++ 11)以及您真正想去的地方(仅传递数字,或者传递类似std::array对您有用)。

If you have C++11 and you just want to pass the numbers, it's probably easiest to do something like: 如果您拥有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};
}

Note that an std::initializer_list doesn't support narrowing conversions, so if you want to store the numbers as float instead of double , you'll need to actually pass float s: 请注意, std::initializer_list不支持缩小转换,因此,如果要将数字存储为float而不是double ,则需要实际传递float

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

Unlike @Chris's solution, however, this does not attempt to enforce passing a given number of arguments -- it just conforms to storing whatever number you pass. 但是,与@Chris的解决方案不同,它不会尝试强制传递给定数量的参数-只是符合存储您传递的任何数量。 In return for that, it's a bit easier to use. 作为回报,它更易于使用。 You don't need to specify the size -- it figures that out from the number of items you pass. 您不需要指定大小,它会从您传递的项目数中得出数字。

If you like that general idea, but insist on an array and C++03 (why?) you can do something like this: 如果您喜欢这个总体思路,但坚持使用数组和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;
}

In this case, I've passed float as a template parameter, but if you're really sure it'll always be float , you can just pass the size, and use float instead of T . 在这种情况下,我已经将float作为模板参数传递了,但是如果您确实确定它将始终为float ,则可以传递大小,然后使用float而不是T

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM