如何在 cpp-winrt idl 文件和 normal/standard cpp class 中使用相同的命名空间名称?

How can I use the same namespace names in cpp-winrt idl file and a normal/standard cpp class?

场景是新的,我认为它可能是 cpp-winrt 模块或 vc 编译器中的错误。

问题
1.使用通用windows.
的cpp-winrt模板创建"windows runtime component" 2.记下idl文件中定义的命名空间名称。默认情况下,idl 文件被命名为 class.idl.
3. 使用 class 向导向项目添加 "new standard cpp class"。
4. 将新的 class 置于与 idl 文件中定义的相同命名空间名称下。
5. 构建项目。
一种。构建应该会成功。
6.在runtime实现中使用标准cppclassclass.
7. 现在再次尝试构建项目。
一种。这次构建将失败。

原因
1. cppwinrt.exe从idl文件生成源文件。
2.运行时实现class命名空间前缀为"winrt".
3. 标准cppclass没有前缀命名空间"winrt".
4. vc 编译器期望标准 cpp class 命名空间从 "winrt"
开始 5. 否则,即使您尝试使用完全限定的命名空间名称,名称解析也会失败。

示例运行时 idl 文件


namespace NMLevel1.NMLevel2
{
    [default_interface]
    runtimeclass Class
    {
        Class();
        void RuntimeMethod1();
        Int32 RuntimeMethod2(Int32 arg1);
        String RuntimeMethod3(String arg1);
        Int32 MyProperty;
    }
}

示例标准 cpp 文件

#pragma once
#include <string>
using namespace std;

namespace NMLevel1::NMLevel2
{
    class StdCPPClass
    {
    public:
        StdCPPClass();
        virtual ~StdCPPClass();

        void method1();
        int method2(int arg1);
        wstring method3(wstring arg1);
    };
}

示例运行时class实现

#include "pch.h"
#include "Class.h"
#include "NMLevel1.NMLevel2.Class.g.cpp"
#include "StdCPPClass.h"

using namespace winrt;
using namespace Windows::Foundation;

namespace winrt::NMLevel1::NMLevel2::implementation
{
    void Class::RuntimeMethod1()
    {
        NMLevel1::NMLevel2::StdCPPClass stdcls;

        Uri uri(L"http://aka.ms/cppwinrt");
        //printf("Hello, %ls!\n", uri.AbsoluteUri().c_str());
        printf("RuntimeMethod1(): Hello, %ls!\n", stdcls.method3(uri.AbsoluteUri().c_str()).c_str());
    }
}

NMLevel1::NMLevel2::StdCPPClass stdcls; is not allowed without prefixing the namespace with winrt.

这是错误还是无法克服的设计限制? 或者如何在 idl 和 cpp 文件中使用相同的命名空间 'NMLevel1::NMLevel2'?

C++ 中的名称查找相当复杂,尤其是当名称空间通过 using 声明实质上合并时。为了帮助编译器识别您想要的名称,您必须明确并使用完全限定名称(而不是示例中的限定名称)。

你必须改变

void Class::RuntimeMethod1()
{
    NMLevel1::NMLevel2::StdCPPClass stdcls;
    // ...
}

void Class::RuntimeMethod1()
{
    ::NMLevel1::NMLevel2::StdCPPClass stdcls;
    // ...
}

注意领先的 :: 范围解析,它将查找限制在全局范围内(或通过 using 声明引入全局​​命名空间的命名空间)。您可以在此处找到更多信息:Qualified name lookup.