この答えは、静的、Cスタイルの配列です::アレイ、私は謝罪します。
私の頭の上には、再帰を行うための2つの方法がありましたが、もっと多くのテクニックがあります。
最初のものは、部分的に特殊化されたクラス(配列カウントが0)を使用して再帰を終了します。
2番目の方法は、オーバーロードされた関数で再帰を終了する静的に選択された型へのキャストを使用します。ここでは、配列をvoid *にキャストしますが、これでは動作しない型に対しては、元の型から構築可能なカスタム型を作成できます。
私はreinterpret_castを使って配列の型を配列[count]への参照から配列[count-1]に変更しました。私はここで使用されているようにこれが安全であることを期待していますが、さまざまな状況で問題に遭遇する可能性があることに留意してください。あなたは私はあなたがあまりにも再帰を「停止」か、あまりにも知っているしたいと仮定している情報から
#include <iostream>
// Ends recursion with a partial specialization
template <typename T, int count>
struct StaticArrayDump {
static void func(T(&a)[count]) {
using shorter_t = T(&)[count-1];
StaticArrayDump<T, count-1>::func(reinterpret_cast<shorter_t>(a));
std::cout << a[count-1] << ' ';
}
};
template <typename T>
struct StaticArrayDump<T,0> {
static void func(...) {}
};
template <typename T, int count>
static void static_array_dump_spec(T(&a)[count]) {
using shorter_t = T(&)[count-1];
StaticArrayDump<T,count>::func(a);
}
// Ends recursion with void* cast and function overload
// Ultimately relies on type_select's specialization, however
template <bool, typename A, typename B> struct type_select /* true */ { using type = A; };
template <typename A, typename B> struct type_select<false,A,B> { using type = B; };
template <bool cond, typename A, typename B>
using type_select_t = typename type_select<cond, A, B>::type;
static void static_array_dump_ovld(...) {}
template <typename T, int count>
static void static_array_dump_ovld(T(&a)[count]) {
static const int next_count = count-1;
using shorter_t = T(&)[next_count];
static_array_dump_ovld(reinterpret_cast<
type_select_t<next_count!=0, shorter_t, void*>
>(a));
// output the last element
std::cout << a[count-1] << ' ';
}
// This is an overload-based version which is free of
// any reliance on template specialization.
// helper_trueol's (void*, void*) overload will only be
// selected for arguments (array_ref, count) when count
// is 0, because 0 is the only integer which can be
// converted to a pointer.
// This one's compiler compatibility is a bit shaky...
// MSVC 2013 OK
// IdeOne g++ needs int cast for next_count
static void helper_trueol(void*, void*) {}
template <typename T, int count>
static void helper_trueol(T(&a)[count], int) {
static const int next_count = count-1;
using shorter_t = T(&)[next_count];
helper_trueol(reinterpret_cast<shorter_t>(a), int(next_count));
std::cout << a[count-1] << ' ';
}
template <typename T, int count>
static void static_array_dump_trueol(T(&a)[count]) {
helper_trueol(a, count);
}
// Finally, this overload-based version relies
// on SFINAE to disqualify the template function
// as a candidate when count is 0 because the
// zero-length array type triggeres a substitution
// failure.
// So just using this template array argument type,
// the same one used in all of the previous examples,
// but without any extra mechanisms, is all you need
// to end this recursion!
// This is the obvious best way, of course.
static void static_array_dump_sfinae(...) {}
template <typename T, int count>
static void static_array_dump_sfinae(T(&a)[count]) {
static const int next_count = count-1;
using shorter_t = T(&)[next_count];
static_array_dump_sfinae(reinterpret_cast<shorter_t>(a));
std::cout << a[count-1] << ' ';
}
//////
int main() {
double dbl_array[] = { 0, 1.2, 3.4, 5.6789, 10 };
static_array_dump_spec(dbl_array);
std::cout << '\n';
const char* cstr_array[] = { "zero", "one", "two", "three", "four" };
static_array_dump_ovld(cstr_array);
std::cout << '\n';
char charray[] = "Hello";
charray[sizeof(charray)-1] = '!'; // replace nul terminator
static_array_dump_trueol(charray);
std::cout << '\n';
bool barray[] = {true, true, true, false, true, false, false, false};
std::cout << std::boolalpha;
static_array_dump_sfinae(barray);
std::cout << '\n';
}
正確には何ですか?その再帰的テンプレートソースを提供できますか? –
例を入れてください。私はただ一つ追加した。 – user2345397