次の問題があります。
template< size_t... N_i >
class A
{
public:
// ...
void foo()
{
bar( /* 0,...,0 <- sizeof...(N_i) many */);
}
};
関数bar
を呼び出してsizeof...(N_i)
多くの引数をすべてゼロにしたいです。たとえば、bar(0,0,0)
の場合はsizeof...(N_i) == 3
です。これはどのように実装できますか?
bar(((void)N_i, 0)...);
コンマ演算子はN_i
を破棄し、右側のオペランドの値(0
)のみを生成します。キャストは、N_i
が破棄されることに関する警告を防ぐためのものです。
間違いなく興味深い answer by @Columbo にもかかわらず、constexpr
のテンプレート変数に基づく別の実行可能なソリューションを提案したいと思います。
#include <cstddef>
template<std::size_t, std::size_t V>
constexpr std::size_t repeat_value = V;
template<std::size_t... N_i>
class A {
template<typename... Args>
void bar(Args&&...) { }
public:
void foo() {
// repeat N_i times value 0
bar(repeat_value<N_i, 0>...);
}
};
int main() {
A<0, 1, 2, 3, 4> a;
a.foo();
}
コンパイル時のパフォーマンスが悪いとしても、少なくとも読みやすいと思います。
次のように簡単に一般化できます。
template<std::size_t, typename T, T V>
constexpr T repeat_value = V;
特定のケースでの呼び出しは次のとおりです。
bar(repeat_value<N_i, int, 0>...);
テンプレートを使用して、同様のものをシミュレートすることもできます。これは非常に基本的なソリューションであり、0のリストを作成するだけですが、必要に応じて他のシーケンスを生成するように拡張することもできます。
template <size_t Unused>
struct Wrap {
static constexpr size_t value = 0;
};
template <size_t... N_i>
class A {
public:
void foo() {
bar(Wrap<N_i>::value...);
}
};
これは、N_i引数と同じサイズのゼロのリストに展開されます。確かに、インターフェースは少し異なります。
バーが受け取る要素の値を示す完全な例については、ここを参照してください。 ライブの例