テンプレートの基本クラスの関数ポインター型へのアクセス
-
21-08-2019 - |
質問
提供されたクラスは本当に変更したくないのですが、拡張したいと思っています。私はパターンとテンプレートの初心者で、テンプレート クラスに適用される Decorator パターンを試しています。テンプレート クラスには、(セマンティクスを正しく理解していれば) さらに別のクラスのメンバーへのポインターが含まれています。メンバーへのポインターは、XML istream のデシリアライザーです。タイプ「T」は、逆シリアル化される XML ドキュメントのタイプです。
template <typename T> class B {
public:
typedef std::auto_ptr<T> MYFUN(
std::istream&, const std::string&, const std::string& );
public:
B<T>( MYFUN* p );
private:
MYFUN *fptr;
std::string aString1;
std::string aString2;
};
読んだ後、typedefは奇妙に見えます http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.5, それでも、このクラスはそのままで問題なく動作するようです。提供されたヘッダー ファイルには追加の #define がないため、これは私にとって少し不思議です。
ここで、MYFUN から返された auto_ptr オブジェクトに対してもう少し作業を行いたいので、Decorator としてそれを拡張しようとします。
template <typename T>
class D : public class B<T>
{
D( B<T>::MYFUN *fPtr, B<T> *providedBase ); //compiler complaint
//Looks like B
private:
B* base_;
};
template <typename T>
D<T>::D( B<T>::MYFUN *p, B<T> *base ) //compiler complaint
:
B<T>::B( p ), base_(providedBase)
{ }
これをコンパイルしようとすると、表示されている 2 行で構文に関する問題が発生します。エラーは「* に ')' が必要です」のようなものです。MYFUN が未定義であることについては不満はありません。
D と同じ署名を使用して D のメンバーへのポインターを再定義すると、つまり、
//change MYFUN to NEWFUN in D)
typedef std::auto_ptr<T> MYNEWFUN(
std::istream&, const std::string&, const std::string& );
これは機能します。私は、B から作成する可能性のあるすべての D/デコレータに対してこれを行う必要がないことを好みます。typedef をよりグローバルに実行しようとしましたが、テンプレート パラメーターが定義されていないため、構文を正しく取得できませんでした。
解決
コンパイル エラーは、コンパイラが型について話していることを認識できないことが原因で発生します。
試す:
D( typename B<T>::MYFUN *fPtr, B<T> *providedBase );
そして
template <typename T>
D<T>::D( typename B<T>::MYFUN *p, B<T> *base )
見る: C++ FAQ Lite のテンプレート セクション これが必要な理由の詳細については説明しますが、要約すると、テンプレートの特殊化の可能性があるため、コンパイラにはそれを確認する方法がないということです。 B<T>::MYFUN
実際には型を指します。
他のヒント
B の MYFUN typedef の定義はプライベート可視性を使用して行われます。D はアクセスできなくなります。これを protected または public に変更すると機能しますか?
template <typename T> class B {
protected:
typedef std::auto_ptr<T> MYFUN(
std::istream&, const std::string&, const std::string& );
...
};
これに関して私が考える問題は、B::MYFUN が プライベート typedef。
したがって、継承クラスはアクセスできません。
これを次のように変更します。
template <typename T> class B
{
public:
typedef std::auto_ptr<T> MYFUN( std::istream&, const std::string&, const std::string& );
public:
B<T>( MYFUN* p );
private:
MYFUN *fptr;
std::string aString1;
std::string aString2;
};