2016-09-22 6 views
4

私は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; 
} 
+3

['std :: initializer_list'](http://en.cppreference.com/w/cpp/utility/initializer_list)を使用してみませんか? – NathanOliver

答えて

6

推測する必要がある場合に、関数のパラメータとして

{ 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を宣言します。

+1

それは型減算の問題であるため、OPは 'Args'の型を指定する必要があるだけなので、' p.set({Param :: D、1000.f}、{param :: p 、2000.f}); 'が動作します。 – SingerOfTheFall

+0

@SingerOfTheFall私は持っていましたが、OPは 'p.set({Param :: D、1000.f}、{Param :: p、2000.f})'にできるだけ近い状態になりたいです。 – NathanOliver

+0

@SingerOfTheFall、情報ありがとうございました。=)この例では動作しますが、実動コードでは 'set'が別の可変テンプレート関数' template Foo(Args ... args){p.set(std :: forward (args)...}} '。そのような場合にはコンパイルされません。 –

関連する問題