1

スカラー型またはインデックス付き型のいずれかを取ることができるテンプレートクラスがあり、その型に応じて異なるバージョンの関数を呼び出したいと思います。

template <typename Ta, typename ... T>
struct MyClass {
    Ta tt; //can be either a scalar (double, complex<double>, int, etc), 
          //or an indexed type (MyClass, std::vector<double>, double[], etc)

    //....

    //I would like the following to be called when tt is a scalar type:
    auto operator[]( size_t i ) { return tt; };

    //I would like the following to be called when tt has [] overloaded:
    auto operator[]( size_t i ) { return tt[i]; };

};

これを行う方法はありますか?戻り値SFINAEは機能しません(この関数にはテンプレートパラメーターがないため)、クラスベースのSFINAEは機能しないようです(可変個引数テンプレートにより、最後にダミーのテンプレートパラメーターが機能しないため)。他のアイデアはありますか?

4

2 に答える 2

4

Xeoは、Andrewが「スカラー」の意味を誤解していたと思います。XeoはスカラーのC/C ++定義(C ++ 11、3.9 / 9による)に従っており、Andrewは線形代数の意味(ベクトル空間の基礎となるフィールドの要素)に近いものを意味していました。たとえば、Andrewstd::complex<double>はスカラーですが、Xeoはそれstd::is_scalar<std::complex<double>>をチェックするために使用するため、これは当てはまりません。もちろん、彼はを取得しfalseます。

アンドリューが望んでいるのはoperator[](size_t i)戻ることだと私は信じています。

  1. tt[i]tt[i]合法である場合; また

  2. tttt[i]違法の場合。

上記の最初の候補を簡単にSFINAEで取り除くことができます。呼び出しが合法であるかどうかをチェックする特性を実装することによりtt[i]、式が合法である場合に2番目の候補をSFINAEで削除することもできます。このトレイトの作成はそれほど単純ではなく、過負荷の解決に依存しています(すべてクラシックno f(...))。トレイトの作成をスキップし、代わりに、内部で同じアイデアを直接使用しますMyClass。ダミー引数での署名の汚染を回避するためoperator[]()に(オーバーロード解決のトリックに必要)value()、ダミー引数を取ると呼ばれるプライベートメソッドを作成します。次にoperator[]()、それらの1つに呼び出しを委任します。

コードは次のとおりです。

#include <type_traits> // for std::declval

template <typename Ta>
class MyClass {

    // This overload is SFINAEd away when tt[i] is illegal
    template <typename T = Ta, typename R = decltype(std::declval<T>()[0])>
    R
    value(size_t i, int) { return tt[i]; }

    // This one is always present but is a worse match than the other
    // one when resolving value(i, 0).
    const Ta&
    value(size_t, ...) { return tt; }

public:

    Ta tt;

    auto operator[]( size_t i ) -> decltype(this->value(0, 0)) {
        return value(i, 0);
    }

};
于 2013-03-12T16:31:15.223 に答える
3

operator[]saダミーテンプレートパラメータを指定するだけです。

template<class U = Ta, EnableIf<std::is_scalar<U>>...>
auto operator[]( size_t i ){ return tt; };

template<class U = Ta, DisableIf<std::is_scalar<U>>...>
auto operator[]( size_t i ) { return tt[i]; };

SFINAEのこの特定のスタイルに関する説明については、ここを参照してください。

于 2013-03-12T01:48:51.827 に答える