Decltype and friend functions in Visual Studio vs G++

auto, c++, c++11, decltype, friend

Solution

The definition of class template `MyClass` is not complete by the time you use the expression `std::begin(a.elts)`, so I guess VC has a reason to complain. You cannot use `operator .` on an incomplete type.

In any case, you could work around that by using the following:

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

Problem

I was writing some C++ code to do vector math. It is essential just a thin wrapper around a `std::array` instance. I wanted to overload the non-member `begin()` function to return an iterator to the beginning of the backing array. To do this, I wrote a simple friend function with an `auto` return type and a trailing return type using `decltype` that just forwarded the call along to the member variable. It wouldn't compile, and I couldn't figure out why. I started fiddling around with a smaller example and discovered the following code compiles under G++ 4.7, but not under the latest 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; } ``` The odd thing was this code only compiled in G++ if the private declaration of `elts` came before the declaration of the `begin()` function. In any case, which compiler is right here? Visual Studio or G++? Edit: The compile error that VS2012 gave was `error C2228: left of '.elts' must have class/struct/union`

Original source