【问题标题】:Using a type without template arguments as a template argument使用没有模板参数的类型作为模板参数
【发布时间】:2022-01-09 12:41:28
【问题描述】:

我有一个名为 Registry 的类,它将 ID 与一些数据相关联。 我想让存储这些对的底层结构可以是用户可以定义的任何std::mapish 类型(例如:std::mapstd::unordered_map)。

我最初的想法是做这样的事情:

template<typename Value, typename Container, typename ID = size_t>
class Registry{
    using Storage = Container<ID, value>;
    static_assert(std::is_same<Storage, std::map> || std::is_same<Storage, std::map>, "Underlying storage type must be a std::map-ish.");
    public:
    Storage<ID, Value> store;
    ...

但是,尝试使用该类会导致错误:

Registry<bool, std::map> testRegistry;
err) argument list for class template std::map is missing

我了解编译器的抱怨,但有什么办法可以解决这个问题,以便这种语法(或类似的东西)可以工作?

感谢您的建议。

【问题讨论】:

    标签: c++ templates template-templates


    【解决方案1】:

    您需要将Container 声明为template template parameter。例如

    template<typename Value, template <typename...> class Container, typename ID = size_t>
    class Registry{
    
        using Storage = Container<ID, Value>;
        static_assert(std::is_same_v<Storage, std::map<ID, Value>> || std::is_same_v<Storage, std::unordered_map<ID, Value>>, "Underlying storage type must be a std::map-ish.");
        public:
        Storage store;
        ...
    

    其他问题:

    • Storage 是一个实例化,所以不要为其指定模板参数。
    • std::map 指定模板参数。
    • 作为static_assert 的条件,您应该使用std::is_same_v(或std::is_same&lt;...&gt;::value

    【讨论】:

    • 感谢您的帮助。我最终使用了template&lt;class, class&gt; class Container,因为我只想要两个值作为地图类型的参数。
    • @Icedude_907 答案已修改。
    • @Icedude_907 容器如 std::mapstd::unordered_map 有超过 2 个模板参数,它们只是默认的,所以你需要更像 template&lt;class, class, class...&gt; class Container 的东西来表明你需要一个接受的类型至少 2 个模板参数,但可以取更多。
    • 目前看起来像这样:template&lt;typename Value, template &lt;class, class, class ...&gt; class Container, typename ID = size_t, typename ...ContainerExtras&gt;using Storage = Container&lt;ID, Value, ContainerExtras...&gt;;
    【解决方案2】:

    作为替代方案,您可以只提供容器,而不是键、值和模板容器:

    template <typename Container>
    class Registry
    {
        using ID = typename Container::key_type;
        using Value = typename Container::mapped_type;
        static_assert(std::is_same_v<Container, std::map<ID, Value>>
                   || std::is_same_v<Container, std::unordered_map<ID, Value>>,
                      "Underlying storage type must be a std::map-ish.");
        // ...
    };
    

    有用法

    Registry<std::map<std::size_t, bool>> testRegistry;
    Registry<std::unordered_map<std::size_t, float>> testRegistry2;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多