使用没有模板参数的类型作为模板参数

Using a type without template arguments as a template argument

我有一个名为 Registry 的 class,它将 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;
    ...

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

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

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

感谢您的建议。

您需要将 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<...>::value代替。

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

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;