1

可変長テンプレートに渡されたテンプレート パラメーターを固定長の配列に入力したいと考えています。その目的のために、次のヘルパー関数テンプレートを作成しました

template<typename ForwardIterator, typename T>
void fill(ForwardIterator i) { }

template<typename ForwardIterator, typename T, T head, T... tail>
void fill(ForwardIterator i) {
  *i = head;
  fill<ForwardIterator, T, tail...>(++i);
}

次のクラス テンプレート

template<typename T, T... args>
struct params_to_array;

template<typename T, T last>
struct params_to_array<T, last> {
  static const std::size_t SIZE = 1;
  typedef std::array<T, SIZE> array_type;

  static const array_type params;

private:
  void init_params() {
    array_type result;
    fill<typename array_type::iterator, T, head, tail...>(result.begin());
    return result;
  }
};

template<typename T, T head, T... tail>
struct params_to_array<T, head, tail...> {
  static const std::size_t SIZE = params_to_array<T, tail...>::SIZE + 1;
  typedef std::array<T, SIZE> array_type;

  static const array_type params;

private:
  void init_params() {
    array_type result;
    fill<typename array_type::iterator, T, last>(result.begin());
    return result;
  }
};

を介して静的定数を初期化しました

template<typename T, T last>
const typename param_to_array<T, last>::array_type
param_to_array<T, last>::params =
  param_to_array<T, last>::init_params();

template<typename T, T head, T... tail>
const typename param_to_array<T, head, tail...>::array_type
param_to_array<T, head, tail...>::params =
  param_to_array<T, head, tail...>::init_params();

今、配列

param_to_array<int, 1, 3, 4>::params

は でstd::array<int, 3>、値13およびが含まれます4。この動作を実現するには、もっと簡単な方法が必要だと思います。助言がありますか?

編集:ノア・ロバーツが彼の答えで示唆したように、私は次のようにプログラムを修正しました:私はパラメータリストの要素を数える新しい構造体を書きました:

template<typename T, T... args>
struct count;

template<typename T, T head, T... tail>
struct count<T, head, tail...> {
  static const std::size_t value = count<T, tail...>::value + 1;
};

template<typename T, T last>
stuct count<T, last> {
  static const std::size_t value = 1;
};

そして、次の関数を書きました

template<typename T, T... args>
std::array<T, count<T, args...>::value>
params_to_array() {
  std::array<T, count<T, args...>::value> result;
  fill<typename std::array<T, count<T, args...>::value>::iterator,
       T, args...>(result.begin());
  return result;
}

今、私は一緒に取得します

params_to_array<int, 10, 20, 30>()

std::array<int, 3>コンテンツを含む1020および30. さらに提案はありますか?

4

2 に答える 2

2

パラメーター パック内の型の数を手動で数える必要はありません。それがsizeof...オペレーターの目的です。さらに、演繹可能なイテレータ型をfill()作成します。明示的に指定する必要はありません。

template<typename T, typename FwdIt>
void fill(FwdIt it) { }

template<typename T, T head, T... tail, typename FwdIt>
void fill(FwdIt it) {
    *it = head;
    fill<T, tail...>(++it);
}

template<class T, T... args> 
std::array<T, sizeof...(args)> params_to_array() {
    std::array<T, sizeof...(args)> a;
    fill<T, args...>(a.begin());
    return a;
};

ただし、パラメーター パックは初期化子リストのコンテキストでも展開できるため、fill()冗長になります。

template<class T, T... args> 
std::array<T, sizeof...(args)> params_to_array() {
    std::array<T, sizeof...(args)> a = {{args...}};
    return a;
};
于 2010-05-18T19:50:00.290 に答える
1

param_to_array の終端の特殊化について私が見ることができる唯一の理由は、次の行です。

static const std::size_t SIZE = params_to_array<T, tail...>::SIZE + 1;

params_to_array メタ関数は配列を作成するため、サイズ N、N-1、....、1 の配列をインスタンス化することになります。したがって、オブジェクトは構成と単一責任ルールの助けを借りることができると思います。パラメーター リスト内の要素をカウントできる別のメタ関数を作成し、このメソッドの代わりに使用します。次に、少なくとも params_to_array でこの再帰を取り除くことができます。

于 2010-05-17T16:15:26.683 に答える