模板参数固定的C++函数参数数量[重复]

Posted

技术标签:

【中文标题】模板参数固定的C++函数参数数量[重复]【英文标题】:C++ number of function's parameters fixed by template parameter [duplicate] 【发布时间】:2013-07-12 03:33:56 【问题描述】:

我有一个这样的模板类:

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;
    ...

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

【问题讨论】:

【参考方案1】:

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

template <unsigned int N>
class Pixel 
public:
    template<typename... Floats> //can't use float... anyway
    Pixel(Floats&&... floats) : colorstd::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

【讨论】:

它是Variadic template。谢谢你,克里斯,你让我第一次知道这个功能。可能我需要去学习 C++11 的新特性。 @OliverQ,它们非常有趣,非常适合研究和使用。可变参数模板是更难理解和使用的模板之一。我通常不擅长将它们正确地用于元编程目的。【参考方案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,哎呀)。

【讨论】:

顺便说一句,std::tuple 仍然是 C++11。不过,总是有boost::arrayboost::tuple【参考方案3】:

这里很大程度上取决于您从哪里开始(C++03 与 C++11)以及您真正想去哪里(只传递数字,或者传递类似 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() 
    pixel1.9, 2.8, 3.7, 4.6, 5.5;

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

pixel1.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 而不是@ 987654332@.

【讨论】:

确实,我打算做所描述的事情,也许是更实际的事情。对于其他更复杂的事情来说,这至少是一个很好的例子。很好的答案。 不错的答案,但您可以使用std::vector 而不是std::array @iammilind:是的——可能有,但是 borgleader 已经证明了这一点,在这种情况下,不清楚它是否一定是唯一(甚至是最好的)选择。这也不是说这是一个坏主意,只是在不知道用法的情况下很难说。 在任何情况下,如果必须在std::arraystd::vector 之间做出选择,则必须是std::array。不仅在性能方面,而且在可读性方面,代码的读者都会确信大小永远不会改变。因为这里的大小在编译时是已知的,所以最好有std::array。只是我的想法:) @iammilind:无论如何,这不是唯一的考虑因素。例如,与std::vector 相比,std::array 的最大大小通常非常有限。

以上是关于模板参数固定的C++函数参数数量[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何模板化一个接受模板化参数并在 C++ 中对其应用模板化函数的函数?

我可以键入检查模板参数吗? (C++)[重复]

C++模板非类型模板参数

具有固定长度数组作为参数的 C++ 构造函数[关闭]

带有函数指针和引用的模板参数推导[重复]

[C++11 模板的改进] --- 可变参数模板