1. ホーム
  2. c++

[解決済み] テンプレート・パラメータに依存する引数が存在しない

2022-02-04 11:52:33

質問

次のようなことをしようとしています。

template <class T>
std::ifstream& operator>> (std::ifstream& fin, List<T> l)
{
    T temp;
    l.resize(0);
    fin >> ignore(1,'\t');
    for(ListIterator<T> i=l.begin();i!=l.end();i++)
    {
        fin >> ignore(1,'\t') >> temp;
        l.push_back(temp);
    }
    return fin;
}

あるファイルからすべての内容を読み込まなければならない。各フィールドは '\t' 文字を無視しなければなりません。 '\t' の文字が表示されます。

エラーログは以下の通りです。

/home/ramy/Documents/C++/Prova/Util.h||In function ‘std::ifstream& Util::operator>> (std::ifstream&, Util::List<T>)’:|
/home/ramy/Documents/C++/Prova/Util.h|431|error: there are no arguments to ‘ignore’ that  depend on a template parameter, so a declaration of ‘ignore’ must be available|
/home/ramy/Documents/C++/Prova/Util.h|431|note: (if you use ‘-fpermissive’, G++ will  accept your code, but allowing the use of an undeclared name is deprecated)|
||=== Build finished: 1 errors, 0 warnings ===|

解決方法は?

組み込み型の場合。 引数依存ルックアップ(ADL) は実行されないので ignore シンボルを現在の名前空間に "import"する必要があります。

例えば、このようにすることができます。最も好ましいものから最も好ましくないものへ(つまり、最も邪魔で名前を汚染するものへ)。

  • foobar::ignore (...)
  • using foobar::ignore; ignore(...);
  • using namespace foobar; ignore(...);

このようにエラーメッセージが出るのは、テンプレートでは、従属名の領域も入力し 二段階ルックアップ . テンプレート・パラメータに依存する名前、例えば

template <typename T> void foo() {
    T x;
    x.frobnicate();
}

は、第2段階 (インスタンス化時) で検索されます。テンプレート・パラメータに依存しない名前、たとえば

class Foo {};

template <typename T> void foo() {
    Foo foo;
    foo.frobnicate();
}

は、最初のフェーズで解決可能でなければならない。

このように分離することで、テンプレートの作者はバグを早期に発見し、正しいシンボルを見つけることができるようになり、テンプレートをより汎用的なものにすることができるようになります。例えば、C#のジェネリックスでは、すべてが解決可能でなければならず、柔軟性に厳しい制限があります(なぜなら、すべてのシンボルが かもしれない によって使用される。 しなければならない が定義されている)。逆に、古いC++コンパイラの中には、第2段階のみ、つまりインスタンス化時に解決するものがあり、ルックアップやエラー検出に微妙な影響を及ぼしていました。

C++の2フェーズモデルは、イーガーモデル(C#)とレイジーモデル(一部の古いC++コンパイラ)の長所を組み合わせたものです。