質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

676閲覧

C++ std::bwck_inserter の実装

mkn66

総合スコア41

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2022/02/17 17:51

C++を勉強中のものです。
使用している教材でstd::back_inserterの実装を説明していたのですが、
分からないことがあったので質問させていただきました。
下記がそのコードです。

C++

1template < typename Container > 2struct back_inserter 3{ 4 back_inserter( Container & c ) 5 : c(c) { } 6 7 8 back_inserter & operator =( const typename Container::value_type & value ) //質問1,2の箇所 9 { 10 c.push_back(value) ; 11 } 12 13 Container & c ; 14} ; 15 16template < typename Container > 17void f( Container const & c ) 18{ 19 // cの全要素をコピーしたい 20 std::vector< typename Container::value_type > temp ; 21 auto out = back_inserter(temp) ; 22 std::copy( std::begin(c), std::end(c), out ) ; 23} 24

質問1
上記のコードの演算子のオーバーロード部分についてです。
テンプレート名Containerの後に :: がついているのはどういう意味なのでしょうか?
テンプレート名に :: がついてもいいのでしょうか?

質問2
質問1と同じ部分についてです。
:: の後にvalue_typeとついているのですが、これはなんなのでしょうか?
typenameがついているので、ネストされた物だと思うのですが、
記述がなくてもコンパイルしてもエラーになりません。 どういうことなのでしょうか?

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

記述がなくてもコンパイルしてもエラーになりません

このコード単体ではエラーにはならないですが、

c++

1Hoge h; 2f<Hoge>(h);

のように実際に利用するコードを書いた際に、クラスHogeにvalue_typeが定義されていなければエラーになります。

投稿2022/02/17 23:32

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mkn66

2022/02/18 03:53

回答ありがとうございます。
guest

0

ベストアンサー

Container はテンプレート引数であり、型名です。
型といっても、ここでは int や double のような型ではなく、
vector<int> や list<double> のようなクラス型であることを仮定しています。
クラスの内部には、メンバ関数やメンバ変数以外にメンバ型があります。

vectorクラスは、template<typename T> class vector { ... }; と定義されて
いるテンプレートクラスで、size や begin といったメンバ関数を持っています。
さらに T という型を外部から参照するために value_type というメンバ型を持っています。
vectorクラスの定義の中で using value_type = T; と宣言されているはずです。

メンバ関数は、オブジェクト名.size のようにして参照しますが、
メンバ型は、クラス名::value_type のようにして参照します。

Container が vector<int> のとき、Container::value_type は int です。
ただ、Container::value_type と書いただけでは、
それがメンバ関数なのかメンバ変数なのかメンバ型なのか分かりません。
そこで typename Container::value_type と書くのです。

追記
質問のコードは本当に教材のコードそのままなんでしょうか?
back_inserter はクラステンプレートなのに、<> を付けない
auto out = back_inserter(temp) ; はエラーになりませんか?
copy の第3引数は output_iterator の要件を満たしていなければいけないのに
back_inserterクラスには *演算子も、++演算子も定義されていません。
標準ライブラリの back_inserter はクラスではなく関数テンプレートであり、
その関数は back_inserter_iteratorクラスのオブジェクトを返します。

次のように書かないと正しく動かないのではありませんか?

C++

1#include <iostream> 2#include <vector> 3 4template <typename Container> 5struct back_inserter_iterator { 6 using container_type = Container; 7 using value_type = void; 8 using pointer = void; 9 using reference = void; 10 using difference_type = void; 11 using iterator_category = std::output_iterator_tag; 12 13 back_inserter_iterator(Container& c) : c(c) { } 14 15 back_inserter_iterator& operator=(const typename Container::value_type & value) { 16 c.push_back(value); 17 return *this; 18 } 19 back_inserter_iterator& operator*() { return *this; } 20 back_inserter_iterator& operator++() { return *this; } 21 back_inserter_iterator& operator++(int) { return *this; } 22 23 Container& c; 24}; 25 26template <typename Container> 27back_inserter_iterator<Container> back_inserter(const Container& c) { 28 return back_inserter_iterator<Container>(c); // クラステンプレートには <> が必要。 29} 30 31template <typename Container> 32void f(const Container& c) { 33 std::vector<typename Container::value_type> temp; 34 auto out = back_inserter(temp); // 関数テンプレートの呼び出しは <> がなくてもよい 35 std::copy(std::begin(c), std::end(c), out); 36 37 for (auto e : temp) std::cout << e << std::endl; 38} 39 40int main() { 41 std::vector<int> a = { 3, 1, 4, 2 }; 42 f(a); 43}

投稿2022/02/17 20:43

編集2022/02/19 04:31
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mkn66

2022/02/18 05:48 編集

分かりやすい説明ありがとうございます。 とてもスッキリしました。 追記 演算子の定義と型名のネストが抜けていました。 すいません。 私もうまく動かなくて悩んでいたところです。 教材には関数back_inserterが記載されていませんでした。 教えてくださりありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問