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.
Unfortunately the linked change to C++/WinRT to produce the better error message is gone, at least for the moment: https://github.com/microsoft/xlang/pull/436
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?)
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.
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...
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.”