【问题标题】:"a function that returns 'auto' cannot be used before it is defined" error despite including the correct c++/winrt headers [duplicate]“在定义之前不能使用返回'auto'的函数”错误,尽管包含正确的c ++ / winrt标头[重复]
【发布时间】:2019-12-24 01:09:07
【问题描述】:

我正在尝试转换一个小型 win32 桌面应用程序以使用 c++/winrt 组件和 XAML 岛。我关注了有关该主题的大量文章,并且确实能够使用一些基本的 XAML 控件来编译和运行应用程序。我的问题是在使用 FileOpenPicker 时出现的,随后出现的错误消息表明“在定义之前不能使用返回‘auto’的函数”。我已经看到其他人通过包含相关的头文件解决了这个问题,但我已经这样做了,但我仍然收到错误。

我已经包含了头文件; - 我尝试包含在 pch 文件和源文件本身中。

#include "pch.h"

#include <winrt/Windows.Storage.h>
#include <winrt/Windows.Storage.Pickers.h>

#include "360MediaPlayer.h"

using namespace winrt;
using namespace Windows::UI;
using namespace Windows::UI::Composition;
using namespace Windows::UI::Xaml::Hosting;
using namespace Windows::Foundation::Numerics;
using namespace Windows::Storage;
using namespace Windows::Storage::Pickers;
using namespace Windows::Media::Playback;


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

#define MAX_LOADSTRING 100

// Global Variables:
HWND _hWnd;
HWND _childhWnd;
HINSTANCE _hInstance;

HINSTANCE hInst;                                // current instance
WCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here.

    _hInstance = hInstance;

    // The main window class name.
    const wchar_t szWindowClass[] = L"Win32DesktopApp";
    WNDCLASSEX windowClass = { };

    windowClass.cbSize = sizeof(WNDCLASSEX);
    windowClass.lpfnWndProc = WndProc;
    windowClass.hInstance = hInstance;
    windowClass.lpszClassName = szWindowClass;
    windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

    //windowClass.hIconSm = LoadIcon(windowClass.hInstance, IDI_APPLICATION);

    if (RegisterClassEx(&windowClass) == NULL)
    {
        MessageBox(NULL, L"Windows registration failed!", L"Error", NULL);
        return 0;
    }

    _hWnd = CreateWindow(
        szWindowClass,
        L"Windows c++ Win32 Desktop App",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL
    );
    if (_hWnd == NULL)
    {
        MessageBox(NULL, L"Call to CreateWindow failed!", L"Error", NULL);
        return 0;
    }



/*    // Initialize global strings
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_MY360MEDIAPLAYER, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }
    */

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY360MEDIAPLAYER));


    // The call to winrt::init_apartment initializes COM; by default, in a multithreaded apartment.
    winrt::init_apartment(apartment_type::single_threaded);

    // Initialize the Xaml Framework's corewindow for current thread
    WindowsXamlManager winxamlmanager = WindowsXamlManager::InitializeForCurrentThread();

    // This DesktopWindowXamlSource is the object that enables a non-UWP desktop application 
    // to host UWP controls in any UI element that is associated with a window handle (HWND).
    DesktopWindowXamlSource desktopSource;
    // Get handle to corewindow
    auto interop = desktopSource.as<IDesktopWindowXamlSourceNative>();
    // Parent the DesktopWindowXamlSource object to current window
    check_hresult(interop->AttachToWindow(_hWnd));

    // This Hwnd will be the window handler for the Xaml Island: A child window that contains Xaml.  
    HWND hWndXamlIsland = nullptr;
    // Get the new child window's hwnd 
    interop->get_WindowHandle(&hWndXamlIsland);
    // Update the xaml island window size becuase initially is 0,0
    SetWindowPos(hWndXamlIsland, 0, 200, 100, 800, 200, SWP_SHOWWINDOW);

    //Creating the Xaml content
    Windows::UI::Xaml::Controls::StackPanel xamlContainer;
    xamlContainer.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() });

    Windows::UI::Xaml::Controls::TextBlock tb;
    tb.Text(L"Hello World from Xaml Islands!");
    tb.VerticalAlignment(Windows::UI::Xaml::VerticalAlignment::Center);
    tb.HorizontalAlignment(Windows::UI::Xaml::HorizontalAlignment::Center);
    tb.FontSize(48);

    MediaPlayer mpSphere = MediaPlayer();


    FileOpenPicker foPicker = FileOpenPicker();
    StorageFile file(foPicker.PickSingleFileAsync().get());

    mpSphere.SetFileSource(file);
    mpSphere.Play();

//  xamlContainer.Children().Append(tb);
    xamlContainer.UpdateLayout();
    desktopSource.Content(xamlContainer);

    //End XAML Island section

    ShowWindow(_hWnd, nCmdShow);
    UpdateWindow(_hWnd);


    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

所以我收到的完整错误消息如下:

错误 C3779 'winrt::impl::consume_Windows_Foundation_IAsyncOperation<:windows::foundation::iasyncoperation>,TResult>::get':返回 'auto '在定义之前不能使用'

尽管上面可以看到头文件的存在。如果我删除处理媒体文件的代码并只留下 XAML 内容,它就会运行。有人知道我错过了什么吗?如果需要,我可以提供完整的项目。

【问题讨论】:

标签: c++ winrt-xaml c++-winrt


【解决方案1】:

您的代码的问题是您缺少 winrt 基础的包含,这是您的代码所必需的,因为它访问异步函数,老实说,大多数 WinRT 代码都需要基础的包含

#include <winrt/Windows.Foundation.h>

using namespace winrt;
using namespace Windows::Foundation;

由于您忘记包含基础包含,编译器无法推断引发错误的类型.....

请注意 auto 关键字对于尾随返回类型形式的函数非常有用,但我强烈建议您不要将它们用于变量,原因有很多,其中一些值得注意的是向量迭代器的奇怪错误,其中即使正确包含在内,在模板函数中 auto 关键字也无法推断类型并会导致错误,

template <typename T>
auto findSomething(:std::string name)
    -> T*
{
    // the code here causes an error since we are trying to deduce the var inside a 
    // template function using auto
    auto _Found = ::std::find_if(somevector.begin(), somevector.end(), [&](::std::pair<::std::string, ::std::unique_ptr<class Someclass>>& pair){ return (pair.first = name) ? true : false; });

    if(_Found != somevector.end())
    {
        return static_cast<T*>(_Found->second.get());
    }
    return nullptr;
}

更正

template <typename T>
auto findSomething(:std::string name)
    -> T*
{
    ::std::vector<::std::pair<::std::string, ::std::unique_ptr<class Someclass>>>::iterator _Found = ::std::find_if(somevector.begin(), somevector.end(), [&](::std::pair<::std::string, ::std::unique_ptr<class Someclass>>& pair){ return (pair.first = name) ? true : false; });

    if(_Found != somevector.end())
    {
        return static_cast<T*>(_Found->second.get());
    }
    return nullptr;
}

如果你不想每次都输入::std::vector&lt;::std::pair&lt;::std::string, ::std::unique_ptr&lt;class someclass&gt;&gt;&gt;::iterator,只需输入别名你的类型机智using关键字using myvectortype = ::std::vector&lt;::std::pair&lt;::std::string, ::std::unique_ptr&lt;class someclass&gt;&gt;&gt;这样你只需要输入myvectortype::iterator....

希望这可以帮助您修复代码。

【讨论】:

  • 丹尼尔做到了!谢谢!
  • @scalpel 我很高兴它做到了(=,您还介意将此标记为您的问题的答案,因为它解决了您的问题,谢谢,祝您有美好的一天(=
  • 这里的重点是,C++/WinRT 使用返回类型推导没有尾随返回类型。您可以在重复的问题(和答案)中找到详细信息。
  • @IInspectable 是的,重要的是要注意这一点,我什至提到它,因为我说编译器无法在没有正确提供的头文件的情况下推断出类型,虽然没有隐含地说,但几乎是在说话虽如此,我只是提到了尾随返回类型,而不是使用 auto 作为变量来帮助 OP 更好地理解 auto 关键字背后的机制及其功能,因为他似乎对这个概念相当陌生(=
猜你喜欢
  • 2019-12-18
  • 2018-03-26
  • 2021-07-21
  • 1970-01-01
  • 2022-07-07
  • 2020-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多