名前空間stdでテンプレートクラスを転送宣言するにはどうすればよいですか?


131
#ifndef __TEST__
#define __TEST__

namespace std
{
    template<typename T>
    class list;
}

template<typename T>
void Pop(std::list<T> * l)
{
    while(!l->empty())
        l->pop();
}

#endif

私のメインでその関数を使用しました。エラーが発生します。もちろん、私はstd::list(アロケーターだと思う)のテンプレートパラメーターが他にもあることを知っています。しかし、それは要点の外です。転送宣言できるようにするには、テンプレートクラスの完全なテンプレート宣言を知っている必要がありますか?

編集:以前はポインタを使用していませんでした-参照でした。ポインタで試してみます。


リストの場合、2番目のパラメータはデフォルトのパラメータですstd::allocator<T>
nakiya

2
STLに前方宣言ヘッダーが含まれていないことは見落としと考えるかもしれません。一方、そのファイルは非常に頻繁に含まれるため、コンパイル時間には何のメリットもありません...
Matthieu M.

7
__TEST__予約済みの識別子です。使用しないください
GManNickG

回答:


146

問題は、テンプレートクラスを前方宣言できないことではありません。はい、正しく前方宣言できるようにするには、すべてのテンプレートパラメータとそのデフォルトを知っている必要があります。

namespace std {
  template<class T, class Allocator = std::allocator<T>>
  class list;
}

しかし、中にさえ、このような前方宣言を行うためには、namespace std明示的に標準で禁止されている:だけあなたがに置くことを許可されている事はstd、テンプレートで専門、一般的に、std::lessユーザー定義型に。他の誰かが必要に応じて関連テキストを引用できます。

ただ、#include <list>それについて心配しないでください。

ああ、ちなみに、二重下線を含む名前は実装で使用するために予約されているため、TEST_Hではなくのようなものを使用する必要があります__TEST__。警告やエラーは生成されませんが、プログラムで実装定義の識別子との競合が発生した場合、正しくコンパイルまたは実行されるとは限りません。形式が正しくありません。また、アンダースコアで始まり、その後に大文字が続く名前も禁止されています。一般に、扱っているマジックがわからない場合は、アンダースコアで始めないでください。


4
namespace stdところで、宣言を転送することが禁止されているのはなぜですか?
nakiya、

4
この回答(stackoverflow.com/questions/307343/…)とリンクされたニュースグループディスカッションを確認してください。
Jon Purdy

7
Jon / Nakiya、#pragma once#ifdefではなく使用してみませんか。最近のほとんどのコンパイラでサポートされています。
Mark Ingram

11
@マーク:#pragmaだから、それが理由です。オプションですが。
Jon Purdy

2
その質問の複製が多数あります。ただ検索する:stackoverflow.com/search
Jon Purdy

20

私はその問題を解決しました。

C ++(Eclipse Juno)でネットワークシミュレーション用のOSIレイヤー(スライダーウィンドウ、レベル2)を実装していました。フレーム(テンプレート<class T>)とその状態(状態パターン、前方宣言)がありました。

解決策は次のとおりです。

では*.cpp、ファイル、あなたはすなわち、前方というヘッダファイルを含める必要があります

ifndef STATE_H_
#define STATE_H_
#include <stdlib.h>
#include "Frame.h"

template <class T>
class LinkFrame;

using namespace std;

template <class T>
class State {

  protected:
    LinkFrame<int> *myFrame;

}

そのcpp:

#include "State.h"
#include "Frame.h"
#include  "LinkFrame.h"

template <class T>
bool State<T>::replace(Frame<T> *f){

そして...別のクラス。


34
using namespaceヘッダーファイルに何かを入れることは、そのヘッダーファイルを使用する誰もが、そうでなければ有効であるローカル名を使用できなくなるため、非常に悪い習慣です。それは基本的に名前空間のポイント全体を打ち負かします。
アンディ・デント

10

前方宣言には、完全なテンプレート引数リストを指定する必要があります。


-5

あなたが使用できる限られた選択肢があります

ヘッダ:

class std_int_vector;

class A{
    std_int_vector* vector;
public:
    A();
    virtual ~A();
};

cpp:

#include "header.h"
#include <vector>
class std_int_vector: public std::vectror<int> {}

A::A() : vector(new std_int_vector()) {}
[...]

実際のプログラムではテストされていないため、完全ではないことが予想されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.