60421


下記コードを参考に出力イテレーターを書いてみたのですがエラーが出てうまくコンパイルが通りません。  
`output_iteratorはclassではない`というような意味のエラーが出るのですが、なぜでしょうか?

参考にしたサイト:[江添亮のC++入門](https://ezoeryou.github.io/cpp-intro/#cb1149)

エラーメッセージ:

[code]

    output_iterator.cpp:17:18: error: 'output_iterator' is not a class, namespace, or enumeration
    output_iterator& output_iterator::operator*() {
                     ^
    output_iterator.cpp:4:8: note: 'output_iterator' declared here
    struct output_iterator {
           ^
    output_iterator.cpp:20:18: error: 'output_iterator' is not a class, namespace, or enumeration
    output_iterator& output_iterator::operator++(int) {
                     ^
    output_iterator.cpp:4:8: note: 'output_iterator' declared here
    struct output_iterator {
           ^
    output_iterator.cpp:23:18: error: 'output_iterator' is not a class, namespace, or enumeration
    output_iterator& output_iterator::operator++() {
                     ^
    output_iterator.cpp:4:8: note: 'output_iterator' declared here
    struct output_iterator {
           ^
    output_iterator.cpp:29:18: error: 'output_iterator' is not a class, namespace, or enumeration
    output_iterator& output_iterator::operator=(const T& x) {
                     ^
    output_iterator.cpp:4:8: note: 'output_iterator' declared here
    struct output_iterator {
           ^
    4 errors generated.
    
[/code]

参考にしたコード:

[code]

    struct cout_iterator
    {
    // --- ボイラープレートコード
        // 出力イテレーターでは使わないのでvoidでいい
        using difference_type = void ;
        using value_type = void ;
        using reference = void ;
        using pointer = void ;
        // イテレーターカテゴリーは出力イテレーター
        using iterator_category = std::output_iterator_tag ;
        // 何もしない
        // 自分自身を返すだけ
        cout_iterator & operator *() { return *this ; }
        cout_iterator & operator ++() { return *this ; }
        cout_iterator & operator ++(int) { return *this ; }
    // --- ボイラープレートコード
    
        // ここが肝心
        template < typename T >
        cout_iterator & operator =( T const & x )
        {
            std::cout << x ;
            return *this ;
        }
    } ;
    
    
    int main()
    {
        std::vector<int> v = {1,2,3,4,5} ;
        cout_iterator out ;
    
        std::copy( std::begin(v), std::end(v), out ) ;
    }
    
[/code]

* * *

自分で書いてみたコード:

[code]

    #include <iostream>
    #include <vector>
    template < typename T >
    struct output_iterator {
        using difference_type = void;
        using value_type = void;
        using reference = void;
        using pointer = void;
        using iterator_category = std::output_iterator_tag;
        public:
            output_iterator& operator*();
            output_iterator& operator++();
            output_iterator& operator++(int);
            output_iterator& operator=(const T& x);
    };
    
    output_iterator& output_iterator::operator*() {
        return *this;
    }
    output_iterator& output_iterator::operator++(int) {
        return *this;
    }
    output_iterator& output_iterator::operator++() {
        return *this;
    }
    
    // assignment implementation
    template < typename T >
    output_iterator& output_iterator::operator=(const T& x) {
        std::cout << x;
        return *this;
    }
    
    int main() {
        std::vector<int> vec = {1, 2, 3, 4, 5};
        output_iterator out;
        std::copy(vec.begin(), vec.end(), out);
    }
    
[/code]


CC BY-SA 4.0
2019-11-11T16:01:07.437
60417
2019-11-12T00:58:14.073
5246
question
c++
C++の出力イテレーターでのエラー

[code]

    template < typename T >
    output_iterator<T>& output_iterator<T>::operator*() {
        return *this;
    }
    template < typename T >
    output_iterator<T>& output_iterator<T>::operator++(int) {
        return *this;
    }
    template < typename T >
    output_iterator<T>& output_iterator<T>::operator++() {
        return *this;
    }
    
    // assignment implementation
    template < typename T >
    output_iterator<T>& output_iterator<T>::operator=(const T& x) {
        std::cout << x;
        return *this;
    }
    int main() {
        std::vector<int> vec = {1, 2, 3, 4, 5};
        output_iterator<int> out;
        std::copy(vec.begin(), vec.end(), out);
    }
    
[/code]

こんな感じでテンプレート引数を追加してみてください。それでエラーは消えるはずです。


CC BY-SA 4.0
2019-11-11T16:50:21.260
60421
2019-11-11T16:50:21.260
33033
60417
answer


コメント欄に書くには長すぎるので回答欄で補足

> 宣言と定義を分けて書くときには

コンパイラから見て、提示例は「宣言と定義を分けて書いている」と解釈できません。最初の `template<typename T> struct
output_iterator` はクラステンプレート、つまり「まだクラスぢゃない」わけです。

一方でクラス定義外（クラステンプレート定義外）に書かれた

[code]

    output_iterator& output_iterator::operator*() {
        return *this;
    }
    
[/code]

は、ごく普通の関数定義です。クラステンプレートのメンバ関数定義とは読めません。

[code]

    class myclass {
        int func(); // メンバ関数の関数宣言
    };
    int func() { ... } //  クラスに属さない関数の関数定義
    
[/code]

と状況は同じです。

コンパイラにとっては `::` の左側 `output_iterator` は定義済み [クラス or 名前空間 or 列挙子]
でなければなりません。クラステンプレートはまだクラスではないのでこの検索の対象になりません。エラーメッセージもその旨主張しています。

「クラステンプレートの」メンバ関数の関数定義と解釈してもらうには `output_iterator<T>` と書かなければならないので最初に
`template <typename T>` が必要、となると @yudedako 氏のコードになります。

クラステンプレートが「まだクラスぢゃない」  
関数テンプレートが「まだ関数ぢゃない」  
のは理解を深めるうえでの重要ポイントです。  
[関数テンプレートと関数のオーバーライドの違いが知りたい](https://ja.stackoverflow.com/questions/49418/)


CC BY-SA 4.0
2019-11-12T00:58:14.073
60427
2019-11-12T00:58:14.073
8589
60417
answer