4

このような完璧に機能するテンプレートが必要です

template <typename container> void mySuperTempalte (const container myCont)
{
    //do something here
}

次に、上記のテンプレートを std::string に特化したいので、

template <typename container> void mySuperTempalte (const container<std::string> myCont)
{
    //check type of container
    //do something here
}

これは機能せず、エラーがスローされます。2番目の例を機能させたいのですが、可能であればテンプレートにコードを追加して、std::vector/std::deque/std::listが使用されているかどうかを確認し、それぞれで異なることを行いたいと思います場合。コードの 99% は vector と deques などの両方で同じであるため、テンプレートを使用しました。

4

6 に答える 6

7

特化するには:

template<> void mySuperTempalte<std:string>(const std::string myCont)
{
    //check type of container
    //do something here
}

ベクトルに特化するには:

template<typename C> void mySuperTempalte (std::vector<C> myCont)
{
    //check type of container
    //do something here
}

deque に特化するには:

template<typename C> void mySuperTempalte (std::deque<C> myCont)
{
    //check type of container
    //do something here
}
于 2009-01-02T14:36:13.497 に答える
7

テンプレートの typename パラメータを試しましたか? このようなコンテナーを宣言するために使用される構文をエミュレートするため、構文は少し奇妙です。これについて詳しく説明しているInformITの優れた記事があります。

template <template <typename> class Container>
void mySuperTemplate(Container<std::string> const& cont) {
}

引数も参照として宣言する必要があることに注意してください。

ちなみにこのコメント

//check type of container

あなたが何か間違ったことをしているという完全な贈り物です。コンテナのタイプをチェックしたくないsep's answer に示されているように、代わりにユーザーにより洗練されたオーバーロードを使用してください。

于 2009-01-02T14:36:13.590 に答える
5

あなたの問題を正しく理解している場合は、STL コンテナーのベクトル、deque などで機能するアルゴリズムがありますが、文字列のテンプレート特殊化を記述しようとしています。この場合、質問で定義した一般化されたテンプレート化されたメソッドを書くことができます:-

template<typename container> void mySuperTempalte( const container &myCont )
{
    // Implement STL container code
}

次に、文字列の特殊化のために宣言します:-

template<> void mySuperTempalte( const container<std::string> &myCont )
{
    // Implement the string code
}

その他の特殊化については、myCont の型宣言を変更するだけです。vector および deque コンテナーに対してこれを行う必要がある場合は、Sep が提案したように、テンプレート パラメーターをコンテナー自体ではなく、そのコンテナーの型のパラメーターにします。

template<typename C> void mySuperTempalte( const std::vector<C> &myCont)
{
    // check type of container
    // do something here
}

最初の実装をすべての STL コンテナーで動作させて作業を楽にすることで、これを回避することを試みる価値があります。そうすれば、文字列クラスの特殊化だけが必要になります。文字列をベクトルに変換して、特殊化をすべて回避することも検討してください。

補足として、コンテナ パラメータを const 参照に変更しました。とにかくオブジェクト const を宣言するので、これが必要だと思います。この方法でコピーを回避します。

于 2009-01-02T20:17:38.317 に答える
4

これまでの回答は役に立ちそうですが、別の構成を使用すると思います。STL コンテナーと同様に、すべてのコンテナーが value_type を定義することを期待しています。したがって、私は書くことができます

inline template <typename C> void mySuperTemplate (C const& myCont)
{
    mySuperTemplateImpl<C, typename C::value_type>(myCont);
}

一般に、明示的に抽出したパラメーターを操作する方が簡単です。

于 2009-01-02T15:30:00.563 に答える
3

@9月

「シンプルな」ソリューション

「sep」が投稿した回答は非常に優れており、おそらく 99% のアプリ開発者にとっては十分ですが、ライブラリ インターフェイスの一部である場合は、いくつかの改善が必要になる可能性があります。

ベクトルに特化するには:

template<typename C> void mySuperTempalte (std::vector<C> myCont)
{
    //check type of container
    //do something here
}

これは、呼び出し元が std::vector を使用していない場合に機能します。ベクトル、リストなどに特化するためにこれが十分に機能する場合は、ここで終了してそれを使用してください。

より完全なソリューション

まず、関数テンプレートを部分的に特化することはできないことに注意してください。オーバーロードを作成できます。それらの 2 つ以上が同程度に一致すると、「あいまいなオーバーロード」エラーが発生します。そのため、サポートするすべてのケースで正確に 1 つの一致を作成する必要があります。

これを行うための 1 つの手法は、enable_if 手法を使用することです。enable_if を使用すると、あいまいな言語ルールを使用して、可能な一致リストから関数テンプレートのオーバーロードを選択的に取り出すことができます...基本的に、ブール式が false の場合、オーバーロードは「見えなくなります」 . 興味がある場合は、SFINAE で詳細を調べてください。

例。このコードは、エラーなしで MinGW (g++ parameterize.cpp) または VC9 (cl /EHsc parameterize.cpp) を使用してコマンド ラインからコンパイルできます。

#include <iostream>
#include <vector>
#include <string>
using namespace std;

template <bool B, class T> struct enable_if {};
template <class T> struct enable_if<true, T> { typedef T type; };

template <class T, class U> struct is_same { enum { value = false }; };
template <class T> struct is_same<T,T> { enum { value = true }; };

namespace detail{
    // our special function, not for strings
    //   use ... to make it the least-prefered overload
    template <class Container>
    void SpecialFunction_(const Container& c, ...){
        cout << "invoked SpecialFunction() default\n";
    }

    // our special function, first overload:
    template <class Container>
    // enable only if it is a container of mutable strings
    typename enable_if<
        is_same<typename Container::value_type, string>::value, 
        void
    >::type
    SpecialFunction_(const Container& c, void*){
        cout << "invoked SpecialFunction() for strings\n";
    }
}

// wrapper function
template <class Container>
void SpecialFunction(const Container& c){
    detail::SpecialFunction_(c, 0);
}

int main(){
    vector<int> vi;
    cout << "calling with vector<int>\n";
    SpecialFunction(vi);

    vector<string> vs;
    cout << "\ncalling with vector<string>\n";
    SpecialFunction(vs);
}

出力:

d:\scratch>parameterize.exe calling
with vector<int> invoked
SpecialFunction() default

calling with vector<string> invoked
SpecialFunction() for strings

d:\scratch>
于 2009-01-02T20:10:06.380 に答える
1

それが良いデザインであるかどうかは、今後の議論に委ねられています。とにかく、部分的なテンプレートの特殊化を使用してコンテナーのタイプを検出できます。特に:

enum container_types
{
   unknown,
   list_container,
   vector_container
};

template <typename T>
struct detect_container_
{
   enum { type = unknown };
};

template <typename V>
struct detect_container_< std::vector<V> > // specialization
{
   enum { type = vector_container };
};

template <typename V>
struct detect_container_< std::list<V> >
{
   enum { type = list_container };
};

// Helper function to ease usage
template <typename T>
container_types detect_container( T const & )
{
   return static_cast<container_types>( detect_container_<T>::type );
}

int main()
{
   std::vector<int> v;

   assert( detect_container( v ) == vector_container );
}
于 2009-01-02T15:34:13.987 に答える