代码之家  ›  专栏  ›  技术社区  ›  C_Rod

在模板方法中确定STL容器中项目的数据类型

  •  0
  • C_Rod  · 技术社区  · 3 年前

    我正在尝试编写一个模板方法来处理STL容器中的项目。获取容器的详细信息很容易(我使用std::enable\u if子句,仅当容器可以迭代时(检测begin()方法),才允许调用此模板方法。)我还需要知道容器所持有的数据类型。以下是有效的方法:

    template <typename CONTAINER>
    std::string doStuff(const CONTAINER & container) {
       using CONTAINER_TYPE = typename CONTAINER::value_type;
    }
    

    我可以使用 if constexpr 在这个方法中做某些事情,如果我还可以确定容器中保存的东西的类型。下面的代码不起作用,但就像我正在尝试的那样:

    template <typename CONTAINER, typename ITEM>
    std::string doStuff(const CONTAINER<ITEM> & container) {
       using CONTAINER_TYPE = typename CONTAINER::value_type;
       using ITEM_TYPE = typename ITEM::value_type;
    }
    

    为什么我不能以这种方式调用该方法,这完全有道理,但我可以做些什么(无论是在调用该方法时,还是在方法内部使用元编程)来确定容器中项目的类型。我希望在编译时知道它。

    (我尝试了decltype和invoke\u result的两种排列,并进行了大量的搜索,但都没有什么效果。)例如,我尝试过:

    using ITEM_TYPE = std::invoke_result<&CONTAINER::begin>::type;
    

    当然,这会返回一个需要取消引用的迭代器类型,但这里的“*”似乎并不像预期的那样工作。

    1 回复  |  直到 3 年前
        1
  •  6
  •   Ted Lyngmo    3 年前

    可以使用模板模板参数:

    template <template <class, class...> class CONTAINER, class ITEM, class... REST>
    std::string doStuff(const CONTAINER<ITEM, REST...>& container) {
       using CONTAINER_TYPE = ITEM; // or `typename CONTAINER<ITEM, REST...>::value_type`
       // This requires SFINAE to not match `ITEM`s without `value_type`:
       using ITEM_TYPE = typename ITEM::value_type;
    
       //...
    }
    
        2
  •  3
  •   Jarod42    3 年前

    您可以简单地添加额外的 typename

    template <typename CONTAINER>
    std::string doStuff(const CONTAINER& container){
       using CONTAINER_TYPE = typename CONTAINER::value_type;
       using ITEM_TYPE = typename CONTAINER_TYPE::value_type;
    }
    

    可能使用一些SFINAE(我将使用C++20方式)

    template <typename CONTAINER>
    std::string doStuff(const CONTAINER& container)
    requires(
        requires {
            typename CONTAINER::value_type::value_type;
        })
    {
       using CONTAINER_TYPE = typename CONTAINER::value_type;
       using ITEM_TYPE = typename CONTAINER_TYPE::value_type;
    }