Visual Studio与G++中的Decltype和friend函数

Decltype and friend functions in Visual Studio vs G++

本文关键字:friend 函数 Decltype 中的 Studio G++ Visual      更新时间:2023-10-16

我正在写一些C++代码来做向量数学。只需在std::array实例周围使用一个薄薄的包装器就可以了。我想重载非成员begin()函数,以便将迭代器返回到支持数组的开头。为此,我编写了一个简单的friend函数,该函数具有auto返回类型和使用decltype的尾随返回类型,该函数只是将调用转发到成员变量。

它无法编译,我也不明白为什么。我开始摆弄一个较小的例子,发现以下代码是在G++4.7下编译的,但不是在最新的VisualStudio2012Professional下编译的。

#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的私有声明先于begin()函数的声明,则此代码仅在G++中编译。

无论如何,哪一个编译器就在这里?Visual Studio还是G++?

编辑:VS2012给出的编译错误为error C2228: left of '.elts' must have class/struct/union

在使用表达式std::begin(a.elts)时,类模板MyClass的定义还不完整,所以我想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);
    }
};