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;
}

奇怪的是,如果私有声明eltsbegin()函数声明之前,则此代码仅在 G++ 中编译。

无论如何,哪个编译器就在这里?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 回答