4

話を続けると、std::initializer_list代わりに単一のパラメーターを使用して、アクセス関数のオーバーロードを作成できることに気付きました。

class array_md
{
    //...
    my_type &        operator []( size_type i )
    { /* Lots of code */ }
    my_type const &  operator []( size_type i ) const
    { /* same Lots of code, with "const" sprinkled in */ }
    my_type &        operator []( std::initializer_list<size_type> i )
    { /* Lots of different code */ }
    my_type const &  operator []( std::initializer_list<size_type> i ) const
    { /* same Lots of different code, with "const" sprinkled in */ }
    //...
};

私のバージョンでは、次のものatがあります。

class array_md
{
    //...
    template < typename ...Index >
    complicated &        at( Index &&...i )  // (1)
    { /* Lots of code */ }
    template < typename ...Index >
    complicated const &  at( Index &&...i ) const  // (2)
    { /* same Lots of code, with "const" sprinkled in */ }
    my_type &            at( std::initializer_list<size_type> i )  // (3)
    { /* Lots of different code */ }
    my_type const &      at( std::initializer_list<size_type> i ) const  // (4)
    { /* same Lots of different code, with "const" sprinkled in */ }
    //...
};

(イニシャライザ リストのエントリの量によって型を変更できないのは実行時であるため、戻り値の型を修正し、エントリの数が間違っている場合はスローします。) 新しいオーバーロードのコードは次のとおりです。mutableとのバージョンで繰り返す必要があるため、constコードを保存する方法を考えています。私は混乱しようとしましたconst_cast

class array_md
{
    //...
    my_type &        operator []( size_type i );
    my_type const &  operator []( size_type i ) const;
    my_type &        operator []( std::initializer_list<size_type> i )
    {
        return const_cast<my_type &>( const_cast<array_md const
         *>(this)->operator [](i) );
    }
    my_type const &  operator []( std::initializer_list<size_type> i ) const;
    //...
};

ここでは、3 番目のバージョンが 4 番目のバージョンを呼び出し、const_castコンパイラの苦情を回避するために使用しています。(最初に平手打ちしたものから削除しているので、トレスパスは問題ありconstません。依存関係を逆にしないでください。mutable真のオブジェクトでメンバー関数を呼び出すことになる可能性がありconstます!) at(3)とマークされたオーバーロードを(4)とマークされたオーバーロードを実装します。しかし、 の代替候補が 3 つあるためat、代わりに (2) が選択されるというエラーが発生しました。ユニバーサルオーバーロードと比較して完全一致を引き起こさないstd::initializer_list内部呼び出しに(値で)渡す方法に何かありますか? at私は普遍的なメソッドの競合を抱えている古くからの友人です。

TL;DR : サンプル コードはstd::initializer_list、関数パラメーター リストで値によって取得されるオブジェクトを示しています。それは、それらを渡す際のコンパイラの最初の優先事項ですか? それとも参照によるものですか?これは、完全一致が必要な場合 (普遍的なオーバーロードを無効にするため) に重要です。

4

1 に答える 1

0

明確化キャスト:

int     f( int );
double  f( double );

template < typename Func, typename ...Args >
void  do_it( Func &&f, Args &&...a );

//...

int  main( int, char *[] )
{
    do_it( (double(*)(double))&f, 5.4 );
    return 0;
}

のコードでmainは、 の 2 番目のバージョンを使用する必要がありfます。この能力はCキャストならではだと思っていましたが、アンダーstatic_castです。だから私は次のようなものを得ました:

class array_md
{
    //...
    template < typename ...Index >
    complicated &        at( Index &&...i );  // (1)

    template < typename ...Index >
    complicated const &  at( Index &&...i ) const;  // (2)

    my_type &            at( std::initializer_list<size_type> i )  // (3)
    {
        return const_cast<my_type &>(
          (
            const_cast<array_md const *>( this )
            ->*
            static_cast<
              my_type const &
              (array_md::*)
              ( std::initializer_list<size_type> ) const
            >( &array_md::at )
          )( i )
        );
    }

    my_type const &      at( std::initializer_list<size_type> i ) const;  // (4)
    //...
};

(関数テンプレートのオーバーロードを区別する必要があるという他の誰かの投稿に答えて、インスピレーションを得ました。)特に中間オブジェクトを作成する必要がない場合は、数回の試行が必要でした。

于 2013-04-30T01:39:54.490 に答える