3

次の例を考えてみましょう

template<class Type = void> class MyClass
{
    public:
        double getValue()
        {
            // if "Type == void" return _x, if "Type != void" return _y
            return (/* SOMETHING */) ? (_x) : (_y);
        }
    protected:
        double _x;
        static const double _y;
}; 

状態は何/* SOMETHING */でしょうか?

_xテンプレートパラメータが無効の場合は戻り、_yそうでない場合は返します。どうやってするか ?

4

5 に答える 5

12

まず、関数の戻り型が。であるため、何も返すことができませんvoid(修繕)

次に、次の場合に異なる動作をするようにその関数を特殊化できTypeますvoid

template<class Type> class MyClass
{
    public:
        double getValue()
        {
            return _y;
        }
    protected:
        double _x;
        static const double _y;
}; 

template<>
inline double MyClass<void>::getValue()
{
   return _x;
}
于 2012-09-26T09:09:54.560 に答える
4

SFINAE を使用して次のように記述できます。

template<typename Type = void>
class MyClass
{
public:
    std::enable_if<std::is_same<Type, void>::value, decltype(_x)> getValue()
    {
        // if "Type == void" return _x, if "Type != void" return _y
        return _x;
    }
    std::enable_if<!(std::is_same<Type, void>::value), decltype(_y)> getValue()
    {
        return _y;
    }
protected:
    double _x;
    static const double _y;
}; 
于 2012-09-26T09:31:08.477 に答える
0

動的キャストを使用して型をテストできます。動的キャストは、キャストが別の型に対して行われた場合、null ポインターを返します。

これが例です。

SomeClass* somePointer = NULL;

somePointer = dynamic_cast<SomeClass*>(someOtherPointer);

if (somePointer) 
{
    // *someOtherPointer is of type SomeClass
} 
else 
{
    // *someOtherPointer is not of type SomeClass
}
于 2012-09-26T09:16:10.623 に答える
0

getValue()今のところ主な問題は、返すように定義したことですvoid。しかし、それはスキップしましょう。C++ での関数定義は、適切に定義する必要があります。これは、不変の戻り値の型と引数リスト、および名前が必要であることを意味します。(私が信じている属性は他にもいくつかありますが、ここではそれほど重要ではありません)。

関数をオーバーロードして、引数リストが異なるいくつかの定義を作成できますが、戻り値の型は同じ名前のすべての関数で同じでなければなりません。テンプレートを使用すると、異なる戻り値の型を取得できます。戻り値の型はテンプレート引数になります。

さまざまなタイプを処理するには、2 つの方法があると思います。1 つは、テンプレートと特殊化を使用することです。

getValue()asを定義してtemplate<T> double getValue();から、さまざまな特殊化を使用して、元の のさまざまなブランチを処理できますgetValue。あなたの例では、次のようになります。

//default case
template<typename T>  double MyClass<T>::getValue() { return _y; }
//void case
template<>  double MyClass<void>::getValue() { return _x; }

2 番目のオプションは、実行時にオブジェクトのタイプを決定できるようにするRTTIメカニズムを使用することです。コードはあなたのコードとほぼ同じです。例えば

    double getValue()
    {
        // if "Type == void" return _x, if "Type != void" return _y
        return (typeid(Type) == typeid(void)) ? (_x) : (_y);
    }

それはすべて、コンパイル中に Type を判別できるかどうかによって異なります。RTTI アプローチには欠点があります。より多くのタイプを処理したい場合は、RTTI を使用すると、別の特殊化を追加する必要があるテンプレート アプローチ中に 1 つの関数を変更することでそれを行うことができます。どちらの道を選ぶかは好み次第だと思います...デザインに関しては、テンプレートの方がはるかに優れています。

編集:おっと...あなたのクラスがによってテンプレート化されているのを見逃しましたType。したがって、RTTIアプローチは問題外に実質的に取り除かれるはずです。とにかく、唯一のタイトルで描かれた誰かがここに来た場合、それはまだ有効な方法であると信じているので、とにかく答えを残します.

于 2012-09-26T09:34:44.893 に答える