Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
600 views
in Technique[技术] by (71.8m points)

c++ - uniform initialization with variadic templates

I have a POD ChParam and it's a parameter in the variadic template function set. I'd like to pass to function arguments(constructor parameters) in curly braces p.set({ Param::D, 1000.f }, { Param::p, 2000.f }). And thought that the constructor will be called implicitly and the ChParam objects will be created. But it's impossible, I should explicitly create an object a.set(ChParam{ Param::D, 1000.f }, ChParam{ Param::p, 2000.f });

is it possible somehow to use the variant 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;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is not directly possible to use

{ Param::D, 1000.f }

as a function parameter when it needs to be deduced. The reason for this is a braced initializer list has no type. Since it does not have a type, a type cannot be deduced by the compiler. You have to help it along. You can do what you did and specify the type like

ChParam{ Param:D, 1000.f }

Or you can specify the type of object you are expecting. If you want a variable numbers of the same types then a std::intializer_list will work. It allows the compiler to construct the elements from the individual braced initializer lists. Using that your code would look like

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

And when you call it you would use

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

Do note the extra set of curly braces used. The outermost set declares the std::intializer_list and each inner set declares each ChParam in the list.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...