これは主に、固定サイズの配列に関連するC ++構文のコーナーに関する質問です。
たとえば、型情報を利用する関数があるとします。
template<class T> void fun(T const& t){
std::cout << typeid(t).name() << std::endl;
}
値または一時オブジェクトを渡すことができます。
int i;
fun(i); // prints "int" ("i" actually)
fun(int{}); // prints "int" ("i" actually)
しかし、私は配列で同じことをすることはできません
double a[10][10];
fun(a); // ok, prints "a[10][10]" ("A10_A10_d" actually)
fun(double[10][10]); // doesn't compile
fun(double{}[10][10]); // doesn't compile
fun(double[10][10]{}); // doesn't compile
fun(double()[10][10]); // doesn't compile
fun(double[10][10]()); // doesn't compile
fun(double(&)[10][10]); // doesn't compile
fun(double(*)[10][10]); // doesn't compile
私は原則として次のことができます。
typedef double a1010[10][10];
fun(a1010{});
しかし、typedefを事前に定義せずに行うことは可能ですか?
関数の引数として固定サイズの配列をインプレースで構築することは可能ですか?
完全なコード:
template<class T> void fun(T const& t){
std::cout << typeid(t).name() << std::endl;
}
typedef double a1010[10][10];
int main(){
int i;
fun(i); // prints "int" ("i" actually)
double a[10][10];
fun(a); // prints "a[10][10]" ("A10_A10_d" actually)
fun(a1010{});
fun(int{}); // prints "int"
/* fun(double[10][10]); // doesn't compile
fun(double{}[10][10]); // doesn't compile
fun(double[10][10]{}); // doesn't compile
fun(double()[10][10]); // doesn't compile
fun(double[10][10]()); // doesn't compile
fun(double(&)[10][10]); // doesn't compile
fun(double(*)[10][10]); // doesn't compile
*/
return 0;
}
ボーナスポイント(おそらく賞金):可変サイズの配列はどうですか?
int N = 10;
f(double[N]);
試してみてください:
fun((int[3]){1,2,3});
fun((int[5]){});
「ボーナスポイント」に関して:可変サイズの配列は言語の一部ではありません。この言語の拡張機能は、テンプレート引数では機能しません。
prog.cc:4:6:注:候補テンプレートは無視されます:置換の失敗:可変的に変更されたタイプ 'int [n]'はテンプレート引数として使用できませんfun(const T&t)
クリスが指摘したように、上記のソリューションは、C ++の拡張である複合リテラルを使用することを提案しています。単純なヘルパークラスを使用して、C ++へのこの拡張を回避するソリューションがあります。
template <class T, std::size_t N>
struct my_array
{
T data[N];
};
template <class T, std::size_t N>
void print(const T (&x)[N])
{
for (auto i: x)
std::cout << i << '\n';
}
int main()
{
print(my_array<int,3>{9,10,11}.data);
}
これはうまく機能しますが、テンプレート引数をmy_arrayに追加する必要がありますが、これは推測されません。C ++ 17では、タイプとサイズを自動的に推測することができます。
template <class T, std::size_t N>
struct my_array
{
constexpr my_array(std::initializer_list<T> x)
{
std::size_t i = 0;
for (auto val : x)
data[i++] = val;
}
T data[N];
};
template <class ...T>
my_array(T...) -> my_array<typename std::common_type<T...>::type, sizeof...(T)>;
int main()
{
print(my_array{9,10,11}.data);
}
2次元配列の場合、これは少し複雑です。
template <class T, std::size_t N1, std::size_t N2>
struct my_array2d
{
constexpr my_array2d(std::initializer_list<std::initializer_list<T> > x)
{
std::size_t i = 0;
for (const auto & row : x) {
int j=0;
for (const auto & val: row) {
data[i][j++] = val;
}
i++;
}
}
T data[N1][N2];
};
int main()
{
work(my_array2d<int, 3, 2>{{9,1},{10,2},{11,3}}.data);
}
二次元配列の演繹ガイドをあきらめましたが、それは可能だと思います。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加