May 30th, 2019

Why does my C++/WinRT project get errors of the form “consume_Something: function that returns ‘auto’ cannot be used before it is defined”?

Last time, we investigated a mysterious error that occurs when linking a C++/WinRT project, and I noted that there’s some good news and some bad news. The good news is that this error message is going away. The bad news is that it’s being replaced with a different error message that you have to learn.

Let’s take another look at the code that triggers this error.

#include <winrt/Windows.Gaming.Input.h>

void CheckGamepads()
{
    auto gamepads =
        winrt::Windows::Gaming::Input::Gamepad::Gamepads();
    for (auto&& gamepad : gamepads)
    {
        check(gamepad);
    }
}

Instead of getting a linker error, you get a compile-time error at the point you attempt to consume an interface whose header file you failed to include.

test.cpp(7): error C3779: winrt::impl::consume_Windows_Foundation_Collections_IIterable<D,winrt::Windows::Gaming::Input::Gamepad>::First': a function that returns 'auto' cannot be used before it is defined
with
[
    D=winrt:::Windows:::Gaming:::Input:::Gamepad
]
note: see declaration of 'winrt::impl::consume_Windows_Foundation_Collections_IIterable<D,winrt::Windows::Gaming::Input::Gamepad>::First'
with
[
    D=winrt::Windows::Gaming::Input::IVisualCollection
]

For the impatient: The problem is that you are missing the header file for the interface you are using. In this case, we are using Windows.Foundation.Collections.IIterable, so we need to include

#include <winrt/Windows.Foundation.Collections.h>

You can read the pull request that makes the change to detect the error at compile time rather than link time.

The trick is that the forward-declared methods are declared as returning auto with no trailing return type and no body. This means “I want the compiler to deduce the return type (but I’m not giving any clues yet).” If you try to call the method before the method has been implemented, then the compiler reports an error because it doesn’t yet have the necessary information to determine the return type.

Hopefully the new error message will make it easier to figure out what went wrong. At least it gives you a file name and line number that points to the place where the unimplemented method is used, and the error mesage includes the name of the type whose definition is missing.

 

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

5 comments

Discussion is closed. Login to edit/delete existing comments.

  • Ian Kemp

    Why not make it even clearer with a short addition:

    a function that returns ‘auto’ cannot be used before it is defined (did you forget to include a relevent header file?)

    • Tim Weis

      That would require a change in the compiler. That’s not something the C++/WinRT team can do. If the compiler team did change the error message, it would eventually show up in code that isn’t C++/WinRT. And when that happens, chances are that including a header file may not be part of the solution.

  • George Gonzalez

    A nitpicker could pick that the new message STILL requires one to think like a compiler, and know that an undeclared interface causes the compiler to generate an auto return type, is that right?   The message, like the old Lance Lawson comic strip, always has the criminal's alibi saying or assuming too much.  How about a stream of conciousness error message explaing the compiler's chain of thought, like "Compiler sees xxxx on line yyy.  No...

    Read more
    • Raymond ChenMicrosoft employee Author

      There is only so much you can do to try to get the compiler to generate a useful error message, since you are not in control of the error message. “some method” + “used before it is defined” hopefully leads you think, “Maybe I should define that thing.”