【问题标题】:uniform initialization with variadic templates使用可变参数模板进行统一初始化
【发布时间】:2016-09-22 13:33:23
【问题描述】:

我有一个 POD ChParam,它是可变参数模板函数 set 中的一个参数。我想在花括号p.set({ Param::D, 1000.f }, { Param::p, 2000.f }) 中传递给函数参数(构造函数参数)。并认为将隐式调用构造函数并创建ChParam 对象。但是不可能,我应该显式创建一个对象a.set(ChParam{ Param::D, 1000.f }, ChParam{ Param::p, 2000.f });

是否有可能以某种方式使用变体p.set({ Param::D, 1000.f }, { Param::p, 2000.f })

#include <iostream>
using namespace std;

using Float = float;

enum class Param : size_t
{
    D = 0,
    p
};
struct ChParam
{
    Param tag_;
    Float value_;
};
class PipeCalcParams
{
private:
    Float D_, p_;
public:
    PipeCalcParams() : D_(0), p_(0) {}
    PipeCalcParams& set_D(Float D) { D_ = D; return *this; }
    PipeCalcParams& set_p(Float p) { p_ = p; return *this; }


    template <typename... Args>
    PipeCalcParams& set(const ChParam& p, Args&&... args) {
        set(p);
        return set(args...);
    }

    PipeCalcParams& set(const ChParam& p)
    {
        switch (p.tag_)
        {
        case Param::D:
            set_D(p.value_);
            break;
        case Param::p:
            set_p(p.value_);
            break;
        }

        return *this;
    }

};

int main() {
    PipeCalcParams a;
    a.set(ChParam{ Param::D, 1000.f }, ChParam{ Param::p, 2000.f });//OK

    PipeCalcParams p;
    p.set({ Param::D, 1000.f }, { Param::p, 2000.f });//error: no matching function for call to 'PipeCalcParams::set(<brace-enclosed initializer list>, <brace-enclosed initializer list>)' p.set({ Param::D, 1000.f }, { Param::p, 2000.f });
    return 0;
}

【问题讨论】:

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


【解决方案1】:

不能直接使用

{ Param::D, 1000.f }

需要推导时作为函数参数。原因是花括号初始化列表没有类型。由于它没有类型,因此编译器无法推断出类型。你必须帮助它。您可以做您所做的并指定类型,如

ChParam{ Param:D, 1000.f }

或者您可以指定您期望的对象类型。如果您想要相同类型的变量编号,那么 std::intializer_list 将起作用。它允许编译器从单独的大括号初始化器列表中构造元素。使用它你的代码看起来像

PipeCalcParams& set(std::initializer_list<ChParam> args)

当你调用它时,你会使用

p.set({{ Param::D, 1000.f }, { Param::p, 2000.f }})

请注意使用的额外花括号。最外面的集合声明std::intializer_list,每个内部集合声明列表中的每个ChParam

【讨论】:

  • 可能需要注意的是,由于是类型推导问题,OP只需要指定Args的类型,所以p.set({ Param::D, 1000.f }, ChParam{ Param::p, 2000.f });就可以了。
  • @SingerOfTheFall 我会拥有,但 OP 希望尽可能接近 p.set({ Param::D, 1000.f }, { Param::p, 2000.f })
  • @SingerOfTheFall,谢谢你的信息,不知道。=) 在这个例子中它会工作,但在生产代码中 set 在另一个可变参数模板函数 template&lt;typename... Args&gt;Foo(Args... args) { p.set(std::forward&lt;Args&gt;(args)...) } 中被调用。在这种情况下,它不会编译。
猜你喜欢
  • 2021-08-20
  • 1970-01-01
  • 2016-07-14
  • 2017-05-15
  • 2018-04-27
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多