【问题标题】:c++20 module export/importc++20模块导出/导入
【发布时间】:2021-11-06 19:28:33
【问题描述】:
// module A
export module A;

import <type_traits>;

namespace test
{
export{
    template<typename T, std::size_t N>
    class Foo;

    template<typename T>
    using Foo1 = Foo<T, 1>;

    template<typename T>
    struct is_Foo : std::false_type {};

    template<typename T, std::size_t N>
    struct is_Foo<Foo<T, N>> : std::true_type {};

    template<typename T>
    constexpr static bool is_Foo_v = is_Foo<T>::value;

    template<typename T>
    concept Foo_t = is_Foo_v<T>;
    }
}
// module B
export module B;

export import module A;

namespace test
{
export{
    template<typename T, std::size_t>
    class Foo{ ... };
    }
}
// module C
export module C;

export import module B;

namespace test
{
export{
    // (1)
    template<Foo_t T>
    constexpr void test_func(const T& t) { ... }
    }
}
// test.cpp

import module C;
using namespace test;

constexpr void test_foo()
{
    // (2)
    constexpr Foo1 f1{1, 2, 3};
    // (3)
    test_func(f1);
    // (4)
    constexpr Foo1 f2{4, 5, 6};
}

(1): 概念 Foo_t 在这里很好用

(2):使用undefined class test::Foo&lt;int, 1&gt;

虽然编译器输出的是未定义类的使用,但IDE还是可以提示我们使用Foo1&lt;int&gt; = Foo&lt;int, 1&gt;;

(3):编译器无此行输出,IDE未报错(红色标注)

(4):同(2)

注意:代码全部经过测试,绝对没有语法错误(如果不编译成模块使用hpp,代码运行正常)

可能有人注意到模块导入有顺序要求,我也测试过,不能解决问题。

在test.cpp文件中,即使我再次导入所有模块,也无法解决问题。而且错误还在使用undefined class test::Foo&lt;int, 1&gt;

// test.cpp
import module A;
import module B;
import module C;

// not work

总结是:

  1. 为什么符号导出失败?

  2. 更令人费解的是,为什么IDE可以找到我们使用的符号(虽然jump to definition不能用来跳转),但是编译器却找不到?

如何解决这个问题?

=============================================

经过各种尝试,我似乎已经解决了上述问题(我将多个模块合并为一个模块,并将原来的内容分成多个子模块),但现在又出现了新的问题。

// module Foo
export module Foo;

export{ 
    template<typename T> struct Foo_trait : std::false_type 
    { 
        constexpr static auto size = 1; 
    }
    constexpr auto a_func_base_on_specialization_type_Foo_trait(...) 
    { 
        ... 
    }
}

// module Bar
export module Bar;

import module Foo;

export
{
    template<typename T, std::size_t N>
    class Baz;

    template<typename T, std::size_t N>
    struct Foo_trait<Baz<T, N>> : std::true_type { 
        constexpr static auto size = N; 
    }
}

template<typename T, std::size_t N>
class Baz { 
    constexpr Baz(something) : 
    data(a_func_base_on_specialization_type_Foo_trait(something)) {} 
}

发现不能用a_func_base_on_specialization_type_Foo_trait来构造Baz类,因为大小还是1而不是N

=============================================

我好像找到了上述问题的原因

https://developercommunity.visualstudio.com/t/c20-modules-fail-to-pick-up-template-specializatio/1189551

【问题讨论】:

  • 我注意到即使我不使用别名(Foo1)而是直接使用Foo,也会报同样的错误。

标签: c++ module visual-studio-2019 c++20


【解决方案1】:

您不能在一个模块 (A) 中声明 test::Foo 并在 另一个 模块 (B) 中定义它。标准说它格式不正确,不需要诊断;根据其实现者的偏好,MSVC 可能会将它们解释为两个不同的模板(就好像它们被命名为 __A::test::Foo__B::test::Foo),但你显然会歧义试图使用一个当两者都可用时。

【讨论】:

  • 但是为什么把它放在头文件(hpp)中它会正常工作呢?可能我理解错了,我以为只要有一个使用别名(Foo1)的类(Foo)的完整定义。
  • 可能你注意到了,我在下面添加了这个问题,即使使用了类名,它仍然会报错。
  • @Life4gal:如果您使用标头,它们是相同的类模板(尽管您可能会遇到 ODR 违规或实例化点问题)。
猜你喜欢
  • 2021-08-11
  • 2021-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-17
  • 2021-06-17
  • 2021-10-18
相关资源
最近更新 更多