6

ベクトル計算を行うための C++ コードを書いていました。std::arrayインスタンスの薄いラッパーだけが不可欠です。begin()バッキング配列の先頭に反復子を返すために、非メンバー関数をオーバーロードしたかったのです。autoこれを行うために、戻り値の型と末尾の戻り値の型を持つ単純なフレンド関数を作成し、それを使用decltypeして呼び出しをメンバー変数に転送しました。

コンパイルできず、その理由がわかりませんでした。小さな例をいじり始めたところ、次のコードが G++ 4.7 ではコンパイルできるが、最新の Visual Studio 2012 Professional ではコンパイルできないことがわかりました。

#include <iostream>
#include <array>

template <typename T, size_t size>
class MyClass {

private:
    std::array<T, size> elts;

public:
    friend auto begin(MyClass &a) -> decltype (std::begin(a.elts)) {
        return std::begin(a.elts);
    }

};

int main(void) {
    MyClass<int, 8> instance;
    auto it = begin(instance);
    std::cout << *it << std::endl;
    return 0;
}

奇妙なことに、関数eltsの宣言の前に のプライベート宣言が来た場合にのみ、このコードは G++ でコンパイルされました。begin()

いずれにせよ、ここにあるのはどのコンパイラですか? Visual Studio または G++?

編集:VS2012が与えたコンパイルエラーはerror C2228: left of '.elts' must have class/struct/union

4

1 に答える 1

7

式を使用するまでにクラス テンプレートの定義がMyClass完了していないため、std::begin(a.elts)VC が文句を言う理由があると思います。operator .不完全型には使用できません。

いずれにせよ、次の方法で回避できます。

#include <iostream>
#include <array>

template <typename T, size_t size>
class MyClass 
{
    // ...

    friend typename std::array<T, size>::iterator begin(MyClass &a)
    //     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    {
        return std::begin(a.elts);
    }
};
于 2013-03-13T00:45:38.560 に答える