16

ヘッダーでテンプレートクラスメソッドを宣言し、ソースファイルで定義するための構文は次のようになります。

myclass.h

template <typename T>
class MyClass {
  public:
    void method(T input);
  private:
    T privVar;
};

myclass.cpp

template <typename T>
void MyClass<T>::method(T input) {
    privVar = input;
}

しかし、メソッドがテンプレートでもある場合はどうなるでしょうか。クラスにメソッドを追加してbasic_stringいますが、関数の実装を作成する方法を知りたいです。

MyString.h

template <class _Elem   = TCHAR,
          class _Traits = std::char_traits<_Elem>,
          class _Ax     = std::allocator<_Elem>>
class String
    : public std::basic_string<_Elem, _Traits, _Ax> {
  private:
    // Types for the conversion operators.
    typedef       _Elem* _StrTy;
    typedef const _Elem* _ConstStrTy;

    //...

  public:
        // Conversion operators so 'String' can easily be
        // assigned to a C-String without calling 'c_str()'.
    operator _StrTy() const {
        return const_cast<_StrTy>(this->c_str());
    }

    operator _ConstStrTy() const {
        return this->c_str();
    }

    // ... Constructors ...

    /*------------ Additional Methods ------------*/

    //! Converts a value of the given type to a string.
    template <class _ValTy> static String ConvertFrom(_ValTy val);

    //! Converts a string to the given type.
    template <class _ValTy> static _ValTy ConvertTo(const String& str);
    template <class _ValTy> _ValTy ConvertTo(void) const;

    //! Checks if a string is empty or is whitespace.
    static bool IsNullOrSpace(const String& str);
    bool IsNullOrSpace(void) const;

    //! Converts a string to all upper-case.
    static String ToUpper(String str);
    void ToUpper(void);

    // ...
};

どうすれば実装できtemplate <class _ValTy> static String ConvertFrom(_ValTy val);ますか?これで、クラステンプレートだけでなく、関数テンプレートも指定する必要があるためです。私が書き込もうとしているコードは有効ではないと確信していますが、それは私が達成しようとしていることを示しているはずです。

MyString.cpp

template <class _Elem, class _Traits, class _Ax>
template <class _ValTy>
String<_Elem, _Traits, _Ax> String<_Elem, _Traits, _Ax>::ConvertFrom(_ValTy val) {
    // Convert value to String and return it...
}

私はテンプレートについてはまったく進んでいません。上記が有効であるかどうか非常に疑わしいだけでなく、書くのが面倒で、あまり読みにくいようです。テンプレートメソッドと、独自のクラスタイプを返す静的テンプレートメソッドを実装するにはどうすればよいですか?ヘッダーでそれらを定義したくないからです。

4

3 に答える 3

22

テンプレート外部のテンプレート メンバー関数の定義の構文は次のようになります。

template <class T> struct A
{
   template <class X> void f();
};

template<class T> template<class X> void A<T>::f()
{
}

したがって、あなたのコードは正しいです。

でテンプレート メンバーを定義して.cppもあまり役に立たないことに注意してください。この場合、このテンプレートで使用する必要があるすべてのタイプを明示的にインスタンス化する必要があります。または、これ以外では使用し.cppないでください。意味がありません。

于 2012-11-12T21:34:58.820 に答える
13

私があなたの質問に答える前に、私に最初に言わせてください:これをしないでください。std::string標準ライブラリが多くのアルゴリズムを実装しているように、代わりにフリー関数を使用して拡張します。stringさらに、 sだけではなく範囲に対してそれを行うことをお勧めしますが、それはより主観的です。

またstd::string、C文字列への暗黙的な変換を回避して、作業を困難にするのではなく、予期しない暗黙的な変換によって引き起こされる可能性のあるさまざまなあいまいなバグからコードを保護することにも注意してください。私はそれらを実装することについて非常に長くそして難しいと思います。.c_str()これについて考えてみてください。コードを書くときに一度入力するのに少し時間がかかります。残りの永遠に、コードを読んだ人は誰でも、コードがCスタイルの文字列として使用されていることをすぐに知ることができstd::stringます。

質問に答えるには、ヘッダーにコードを入力するだけです。

//! Converts a value of the given type to a string.
template <class _ValTy> static String ConvertFrom(_ValTy val)
{
    // Code here
}

最後に、アンダースコア+大文字で始まる識別子(およびで始まる他の多くのもの_)はコンパイラー用に予約されているため、プログラムの機能に関してはすべての賭けが無効になっていることに注意してください。

于 2012-11-12T21:19:47.840 に答える
2

あなたの関数定義は有効であり、クラス宣言の外でより簡潔な方法で定義することはできません。関数定義を .cpp ファイルに入れたいので、関数定義をより簡潔な関数宣言と組み合わせることを利用することはできません。関数定義を .cpp ファイルに入れることで、テンプレート クラスの必要なすべての特殊化を明示的にインスタンス化する必要もあります。

于 2012-11-12T21:20:41.160 に答える