C++ 使用可变数量的浮点参数

C++ 使用可变数量的浮点参数,c++,c++11,templates,variadic-templates,C++,C++11,Templates,Variadic Templates,我正在尝试为我的结构多项式实现一个灵活的构造函数: struct Polynomial { std::vector<float> coefficients; size_t degree; }; 我尝试了可变模板: template<float... Args> Polynomial(Args... args); 但这确实不安全 目前我正在使用: Polynomial(std::vector<float>); 所以我想知道是否有一个好的方法

我正在尝试为我的结构多项式实现一个灵活的构造函数:

struct Polynomial
{
    std::vector<float> coefficients;
    size_t degree;
};
我尝试了可变模板:

template<float... Args>
Polynomial(Args... args);
但这确实不安全

目前我正在使用:

Polynomial(std::vector<float>);
所以我想知道是否有一个好的方法来做到这一点

谢谢大家!

您可以使用:

#包括
#包括
结构多项式{
向量系数;
标准:大小和程度;
多项式(std::初始值设定项\u list init)
:coeffs{init},度(init.size()){}
};
int main(){
多项式p{1,2,3};
}

回答您的问题

我想知道是否有一个好的方法来做到这一点

是的,我认为你这样做是完全可以接受的。甚至是使用它的语法
多项式P({f1,f2,f3})一点也不难看

此外,使用
std::vector
与变量法一样有效,而且对其他人来说更容易理解


使用可变方法,您会发现很难强制接收到的类型为
float
,但是使用
std::vector
您可以控制它

。您可能想看看的构造器的灵感。例如,采用两个迭代器的模板化构造函数非常灵活:

template<typename T>
Polynomial(T begin, T end) : coefficients(begin, end), degree(coefficients.size()) {}

auto init = std::vector<float>{2.0, 1.0, 4.0};
Polynomial p2{init.begin(), init.end()};
模板
多项式(T begin,T end):系数(begin,end),阶数(系数.size()){}
autoinit=std::vector{2.0,1.0,4.0};
多项式p2{init.begin(),init.end()};
或者您可以按照Jodocus的建议,使用
std::initializer\u list

您可以有一个采用任何容器类型的模板化构造函数:

template<typename T>
Polynomial(T container) 
: coefficients(begin(container), end(container))
, degree(coefficients.size()) {}

auto init = std::vector<float>{2.0, 1.0, 4.0};
Polynomial p2{init};
模板
多项式(T容器)
:系数(开始(容器)、结束(容器))
,度(系数.size()){}
autoinit=std::vector{2.0,1.0,4.0};
多项式p2{init};


或者您可以提供不同构造函数的组合以满足不同的需求。

您这样做的方式是一种“好方法”。假设调用方希望传递100个系数。如果使用variadics,则会强制调用方执行以下操作:

float c1,c2,c3,....c100;
// init them
Polynomial P(c1, c2, c3,....,c100);
如果我使用100个系数,我肯定会将它们存储在一个向量中,将它们传递给多项式会相当麻烦:

auto coeffs = std::vector<float>(100);
Polynomial P(coeffs[0],coeffs[1],....,coeffs[100]);
另一方面,使用
std::vector
但不允许使用不同的容器是一种任意限制。更好的方法是接受迭代器,并让调用方执行以下操作:

Polynomial P(coeffs.begin(),coeffs.end());

可以使用递归模板处理参数。一般的想法是使用一种私有方法,将第一个参数添加到
系数
向量中,并与其他参数一起递归,直到它们全部被处理:

struct Polynomial
{
    template<class...Args>
    Polynomial(Args... coeffs) {
        init(coeffs...);
        degree = coefficients.size() - 1;
    }
    std::vector<float> coefficients;
    size_t degree;
private:
    void init(float coeff) {
        coefficients.push_back(coeff);
    }
    template<class...Args> void init(float first, Args...others) {
        init(first);
        init(others...);
    }
};
struct多项式
{
模板
多项式(参数…系数){
初始(系数…);
度=系数。大小()-1;
}
std::向量系数;
大小与程度;
私人:
无效初始值(浮动系数){
系数。推回(系数);
}
模板void init(先浮动,参数…其他){
初始(第一);
初始(其他…);
}
};
我认为你的方法(向量参数,或者更好的是初始化列表)是一个好方法

另一种方法(简单但有缺点)是使用缩小,以确保
arg…
float
或可以缩小为
float
的类型。差不多

struct Polinomial
 {
   std::vector<double>  v;
   std::size_t          degree;

   template <typename ... Args>
   Polinomial (Args const & ... args)
      : v { float{args}... }, degree { sizeof...(Args) }
    { }
 };
但您的构造函数不接受整数或
double
长double
值;所以

Polinomial p { 2.3f, 3.5f, 6.7 };
// ........................^^^  double, error

Polinomial p { 2.3f, 3.5f, 6 };
// ........................^  int, error

而且可能限制性太强了。

“但这会迫使通话像”。。。这有什么不对?对于调用者来说,接受向量比接受变量更灵活。如果用户输入任意系数会发生什么?为什么构造函数
多项式p{1,2,3.}不需要
()
。只是问一下,我从来没有见过这种情况。@另外,这是统一初始化,它是在C++11中添加的。您可以查阅C++引用的所有初始化规则,包括具有<代码>初始化列表列表> /COD>构造函数的特性。谢谢,我将用@ Max 66解决方案检查差异。我想我会保留这三种方法谢谢你的回答,这是我试图做的,但实际上可能会限制我,我会看看我是否需要其他类型,但目前我认为这将是足够的
auto coeffs = std::vector<float>(100);
Polynomial P(coeffs[0],coeffs[1],....,coeffs[100]);
Polynomial P({c1,c2,c2});
Polynomial P(coeffs);
Polynomial P(coeffs.begin(),coeffs.end());
struct Polynomial
{
    template<class...Args>
    Polynomial(Args... coeffs) {
        init(coeffs...);
        degree = coefficients.size() - 1;
    }
    std::vector<float> coefficients;
    size_t degree;
private:
    void init(float coeff) {
        coefficients.push_back(coeff);
    }
    template<class...Args> void init(float first, Args...others) {
        init(first);
        init(others...);
    }
};
struct Polinomial
 {
   std::vector<double>  v;
   std::size_t          degree;

   template <typename ... Args>
   Polinomial (Args const & ... args)
      : v { float{args}... }, degree { sizeof...(Args) }
    { }
 };
Polinomial p { 2.3f, 3.5f, 6.7f };
Polinomial p { 2.3f, 3.5f, 6.7 };
// ........................^^^  double, error

Polinomial p { 2.3f, 3.5f, 6 };
// ........................^  int, error