首页 > 解决方案 > C++ 模块导出类

问题描述

// random.ixx
export {
        struct random_trait;

        class engine;
    }

struct random_trait
    {
        using bits64_type = std::uint64_t;
        using bits32_type = std::uint32_t;
        using size_type = std::size_t;

        constexpr static bits64_type default_seed = static_cast<bits64_type>(1234567890);

        template <std::unsigned_integral T, size_type N>
        struct type_generator
        {
            using result_type = std::conditional_t<
                std::is_same_v<T, bits64_type> or
                std::numeric_limits<T>::digits == std::numeric_limits<bits64_type>::digits,
                bits64_type,
                std::conditional_t<
                std::is_same_v<T, bits32_type> or
                std::numeric_limits<T>::digits == std::numeric_limits<bits32_type>::digits,
                bits32_type,
                nullptr_t
                >
            >;
            using state_type = std::array<result_type, N>;

            static_assert(!std::is_same_v<result_type, nullptr_t>, "not supported type");
        };

        template <size_type N>
        using bits64_generator = type_generator<bits64_type, N>;
        template <size_type N>
        using bits32_generator = type_generator<bits32_type, N>;
    };

template <typename T>
    concept generated_type = requires
    {
        typename T::result_type;
        typename T::state_type;
    };

template <generated_type T>
    struct seed_generator final
    {
        using result_type = typename T::result_type;
        using state_type = typename T::state_type;

        constexpr result_type operator()() noexcept
        {
            ...
        }

        constexpr state_type generate_seeds() noexcept
        {
            ...
        }

        result_type seed_;
    };

template <generated_type T>
    class engine_base
    {
        using engine_base_reference = engine_base<T>bitand;
        using const_engine_base_reference = const engine_base<T>bitand;
        using engine_base_rreference = engine_base<T>and;
    public:
        using result_type = typename T::result_type;
        using state_type = typename T::state_type;

        constexpr static auto bits_of_this = std::numeric_limits<result_type>::digits;

        constexpr explicit engine_base(state_type state) noexcept : state_(std::move(state)) {}

        constexpr explicit engine_base(result_type seed = random_trait::default_seed) noexcept
            : state_(seed_generator<T>{seed}.generate_seeds()) {}
    }

class engine64_x4_base : public engine_base<random_trait::bits64_generator<4>>
    {
    public:
        using engine_base::engine_base;

    protected:
        using engine_base::state_;
    }

class engine final : public engine64_x4_base
    {
    public:
        using engine64_x4_base::engine64_x4_base;
    };

// test.cpp
engine e{};
// error: 
// this overload call is ambiguous, it may be engine64_x4_base(void) 
// or 
// engine64_x4_base(unsigned __int64) (this is inherited from engine_base) 
// unsigned __int64 is engine_base's result_type, so it is engine_base(result_type seed = random_trait::default_seed)

问题是为什么会有歧义?或者为什么有默认构造(engine64_x4_base(void))?

然后我试着把所有的代码放到hpp文件中,所有的问题都解决了,也按预期运行了(虽然IDE有个错误说找不到引擎的operator()())。

这是一个模块问题,但我不知道如何解决它。我还应该导出基类吗?

因为我删除了一些不影响问题的函数(这些类的一些成员函数),这使得继承关系看起来很有趣,请不要介意:)

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

终于找到了导出engine_base的解决方案(但是继承链中间的engine64_x4_base不需要导出)。

一切都按预期工作,但我无法理解,因为 engine_base 需要导出是非常不合理的。

还有一点需要注意的是,如果我给引擎构造一个参数而不导出engine_base(尽量避免无缘无故不给参数造成的歧义),编译器会输出“Internal Compiler Error: When generated a constructor for engine (constexpr 显式引擎(__uint64 种子) noexcept)"

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

解决方案


推荐阅读