функция, возвращающая 'auto', не может использоваться, пока не будет определена ошибка, несмотря на включение правильных заголовков c ++ / winrt

Я пытаюсь преобразовать небольшое настольное приложение 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 :: consumer_Windows_Foundation_IAsyncOperation ‹winrt :: Windows :: Foundation :: IAsyncOperation‹ winrt :: Windows :: Storage :: StorageFile ›, TResult› :: get': функция, возвращающая 'auto', не может быть используется до его определения '

несмотря на наличие файлов заголовков, как видно выше. Если я удалю код, связанный с файлом мультимедиа, и оставлю только материал XAML, он запустится. Кто-нибудь знает, что мне не хватает? При необходимости могу предоставить полный проект.


person scalpel    schedule 18.08.2019    source источник
comment
Сузьте его до минимального воспроизводимого примера, пожалуйста. Это должно быть одним из первых шагов в процессе отладки, прежде чем вы обратитесь за помощью! Если я удалю код, связанный с файлом мультимедиа, и оставлю только материал XAML, он запустится. Тогда хорошим началом будет абстрагироваться от всего, кроме кода, имеющего дело с файлом мультимедиа.   -  person Lightness Races in Orbit    schedule 18.08.2019
comment
Вы уже читали эту статью: Почему в моем проекте C ++ / WinRT возникают ошибки форма «consumer_Something: функция, возвращающая 'auto', не может быть использована до того, как она будет определена»?? Это должно помочь вам понять, какой заголовок отсутствует. Вы также должны показать нам все сообщение об ошибке, чтобы мы могли вам помочь.   -  person VolkerG    schedule 18.08.2019


Ответы (1)


auto Ключевое слово просто попросить компилятор во время компиляции определить тип с любым типом, который вы используете, чтобы использовать его в качестве, возможно, возврата из функции или жестко запрограммированного типа POD, такого как int.

проблема с вашим кодом заключается в том, что вам не хватает включения для основы winrt, которая требуется для вашего кода, поскольку он обращается к функциям Async, честно говоря, для большинства кода 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<::std::pair<::std::string, ::std::unique_ptr<class someclass>>>::iterator, просто введите псевдоним вашего типа с using ключевым словом using myvectortype = ::std::vector<::std::pair<::std::string, ::std::unique_ptr<class someclass>>>, тогда вам нужно будет набирать только _8 _....

надеюсь, это помогло вам исправить ваш код.

person daniel    schedule 18.08.2019
comment
Вот и все, Даниэль! Спасибо! - person scalpel; 19.08.2019
comment
@scalpel, я счастлив, что это сделал (=, также не могли бы вы отметить это как ответ на свой вопрос, так как он решил вашу проблему, спасибо и хорошего дня (= - person daniel; 19.08.2019
comment
Важным моментом здесь является то, что C ++ / WinRT использует вывод типа возвращаемого значения без конечного возвращаемого типа. Подробности вы найдете в повторяющемся вопросе (и ответе). - person IInspectable; 19.08.2019
comment
@IInspectable, да, важно отметить это, и я даже упомянул об этом, поскольку я сказал, что компилятор не может вывести тип без правильно предоставленного файла заголовка, который, хотя и не косвенно говорит, в значительной степени говорит о том, что, я только что упомянул конечный возвращаемые типы, а не использование auto для переменных, чтобы помочь OP лучше понять механику ключевого слова auto и его функциональность, поскольку он казался довольно новым для этой концепции (= - person daniel; 19.08.2019