2011-06-25 6 views
10

Stackの実装に使用するコンテナをユーザーが選択できるように、Stackクラスを作成します。たとえば、List/VectorC++テンプレートテンプレート(ダブルテンプレート?)

部分コード:

stack.h

#ifndef STACK_H_ 
#define STACK_H_ 

template <typename T, template<typename T> class ContainerType> 
class Stack{ 
    ContainerType<T> container; 
public: 
    Stack() : container(ContainerType<T>()){} 

}; 

#endif /* STACK_H_ */ 

TEST.CPP

#include "stack.h" 
#include <vector> 

int main(){ 
    Stack<int, std::vector<int> > stack; 
    return 0; 
} 

まあ、それはコンパイルされません。

Stack<int, std::vector<int> > stack; 

エラー:

expected a class template, got `std::vector<int, std::allocator<int> >' test.cpp 

invalid type in declaration before ';' token test.cpp 

type/value mismatch at argument 2 in template parameter 
list for `template<class T, template<class T> class ContainerType> 
class Stack' test.cpp 

‪ 
+3

ベクトルはstdネームスペースにあります – nullpotent

+0

このエラーは、常に 'using namespace std;'を書いて慣れていることの結果です。 –

+0

@Armenしかし、実際のエラーは別の場所です。 –

答えて

22

vectorstd名前空間に存在するので、それは、std::vector、何もないのだろうとstd::vector<int>はもうテンプレートではありませんしながら、あなたは、テンプレートテンプレートパラメータを求めています。あなたが優れているので、

template < 
    typename T, 
    template<typename, typename> class ContainerType, 
    typename Alloc = std::allocator<T> 
> 
class Stack{ 
    ContainerType<T, Alloc> container; 
    // ... 
}; 

// usage: 
Stack<int, std::vector> s; 

は今、これが唯一の基になる型などの2つのテンプレートパラメータでコンテナを可能にします。次に、std::vectorは実際にテンプレートパラメータ、タイプ用とアロケータのために他を取りますノーマルタイプとしてそれを取る:標準が何をするかとオフ、あなたが偽の「静的アサート」を行うことができます基になる型が同じTを持っていることを保証するために

template <typename T, typename ContainerType> 
class Stack{ 
    ContainerType container; 
    // ... 
}; 

// usage: 
Stack<int, std::vector<int> > s; 

、またはあなたがCを持っている場合++ 0xを有効にしたコンパイラでは、実際の静的なアサートを行うことができます:

#include <tr1/type_traits> // C++03 us std::tr1::is_same 
//#include <type_traits> // C++0x, use std::is_same 

template <typename T, typename ContainerType> 
class Stack{ 
    typedef typename ContainerType::value_type underlying_value_type; 
    typedef char ERROR_different_value_type[ 
       std::tr1::is_same<T, underlying_value_type>::value ? 1 : -1 
             ] 
    ContainerType container; 
    // ... 
}; 

Tが使用される容器のTと異なる場合、それはtypedef char ERROR_different_vale_type[-1]なり、負のサイズの配列はおそらく、コンパイラエラーが発生している、存在することができないので、これが動作します。 :)に今、あなたができるだけstatic_assertそのC++ 0xで:便宜上

#include <tr1/type_traits> // C++03 
//#include <type_traits> // C++0x 

template <typename T, typename ContainerType> 
class Stack{ 
    typedef typename ContainerType::value_type underlying_value_type; 
    static_assert(std::tr1::is_same<T, underlying_value_type>::value, 
    "Error: The type of the stack must be the same as the type of the container"); 
    ContainerType container; 
    // ... 
}; 

、あなたは今、一般的な場合のデフォルトのテンプレート引数を指定することができます。

template <typename T, typename ContainerType = std::vector<T>> 
class Stack{ 
    ContainerType container; 
    // ... 
}; 

// usage: 
Stack<int> s; 

そして、この時点であなたをちょうどこれを行うstd::stackを使うことができます(ただし、基底型としてstd::dequeを使用しています)。:)

+0

はい、私はStack >もスタックだけでなく、書き込むことができます。 2番目のコードブロックを使用すると、私が使用すると何が起こりますか:Stack >スタック。それは単なる二重ベクターであろうか?ベクトルがint型でdouble型ではないようにconstraintを作ることができますか(つまり、最初の型と同じようになります)? – user550413

+0

@ user550413: 'Stack 'と書くと、コンテナのタイプは 'List 'になります。 'Stack 'が 'vector'を取得したときとまったく同じです。 – vines

+0

@user:第2版については、私の編集を参照してください。 – Xeo

1

このライン:

 Stack<int, vector<int> > stack; 

は次のようになります。

Stack<int, std::vector<int> > stack; 

か、接頭辞ができ、私はライン上の次のエラーを取得しますまず

using namespace std; 
+0

'std :: vector'だけを使う必要があるときに、なぜ名前空間std全体を持ってくるのですか? –

+0

上記の新しいエラーが編集されました。 – user550413

+0

@ user550413他の回答を見てください。 –

2

vectorstd名前空間に属しているため、修飾する必要があります。しかしContainerTypeとして、それ以外は、テンプレートではなく、最終的なタイプを渡す必要があるテンプレートテンプレートパラメータは次のとおりです。

Stack<int, std::vector > stack; 
2

ためのアリティの問題で、テンプレートテンプレートパラメータを使用するためにされていない最も簡単な方法コンテナ。

代わりに、完全なコンテナタイプを渡すだけです。次に、value_type(標準STL内部typedef)を抽出して値を取得します。

template <typename Container> 
class Stack 
{ 
public: 
    typedef typename Container::value_type value_type; 

private: 
    Container _container; 
}; // class Stack<Container> 

あなたは、その後、単に、Stack< std::vector<int> >として使用することができ、それがint Sが含まれています。

関連する問題