【问题标题】:How to realize template class type in template function?如何在模板函数中实现模板类类型?
【发布时间】:2021-07-19 04:18:01
【问题描述】:

我想为STL容器设计一个打印功能,包括:std::vector, std::map, std::unodered_map, std::set, std::unordered_set, std::list ....

理想的函数如下所示:

template<typename T>
void Show(const T& t)
{
    if (istype(t, std::vector)) 
    {  
        // here is a presudo code
        // print vector
        for (auto i: t) cout << i << endl;
    } 
    else if (istype(t, std::unordered_map)) 
    {
        // print unordered_map
    } 
    else 
    {  }
}

我认为问题发生在istype()

我知道有像std::is_same 这样的功能可以做到这一点。

但是好像只能在intfloat上操作,不能在std::vector上操作,你能帮忙吗?

【问题讨论】:

    标签: c++ templates c++17 c++-standard-library function-templates


    【解决方案1】:

    但是好像只能在int或者float上操作,不能操作 在std::vector,你能帮忙吗?

    对于像搁浅容器这样的模板类,您需要指定模板参数来获取具体类型,然后您可以使用std::is_same 进行比较。这意味着像 std::is_same_v&lt;T, std::vector&lt;int&gt;&gt;std::is_same_v&lt;T, std::vector&lt;float&gt;&gt; 之类的东西......将起作用。

    另一方面,您需要查看传递的容器是否是标准容器的特化。你需要你自己的std::is_same_v,比如类型特征。

    一种可能的实现如下所示。另请注意,您需要使用if constexpr(自)而不是普通的if 进行编译时分支。如果无法访问,则需要使用SFINAE

    (See a Demo)

    #include <iostream>
    #include <type_traits> // std::false_type, std::true_type
    #include <vector>
    #include <list>
    #include <string>
    #include <map>
    
    template<typename Type, template<typename...> class Args>
    struct is_specialization final : std::false_type {};
    
    template<template<typename...> class Type, typename... Args>
    struct is_specialization<Type<Args...>, Type> : std::true_type {};
    
    
    template<typename ContainerType>
    constexpr void show(const ContainerType& container) noexcept
    {
        if constexpr (is_specialization<ContainerType, std::vector>::value
                    || is_specialization<ContainerType, std::list>::value)
        {  
            for (const auto ele : container)
                std::cout << ele << '\t';
            std::cout << '\n';
        }
        else if constexpr (is_specialization<ContainerType, std::map>::value)
        {
            for (const auto& [key, value]: container)
                std::cout << key << " " << value << '\t';
            std::cout << '\n';
        }
        // ... so on!
    }
    
    int main()
    {
        std::vector<int> vec{ 1, 2, 3 };
        show(vec);
    
        std::list<int> list{ 11, 22, 33 };
        show(list);
    
        std::map<int, std::string> mp{ {1, "string1"}, {2, "string2"}, {3, "string3"} };
        show(mp);
    }
    

    【讨论】:

      【解决方案2】:

      所有 STL 容器的共同特点是它们可以在[begin(),end()) 范围内迭代。对于序列容器,您必须将打印T 作为 value_type 处理,对于(无序)关联容器打印 std::pair&lt;const Key, T&gt; 作为 value_type 必须进行处理。就这些。我看不出有任何理由在您的实现中检查传递的容器的类型。

      template<class T>
      void Print(const T& val) {
          std::cout << val;
      }
      
      template<class Key, class Value>
      void Print(const std::pair<const Key,Value>& p) {
          Print(p.first);
          std::cout << " - ";
          Print(p.second);
      }
      
      template<class Cont>
      void PrintCont(const Cont& cont) {
          std::cout << std::endl;
          for (auto it = cont.begin(); it != cont.end(); ++it) {
              Print(*it);
              std::cout << " ";
          }
          std::cout << std::endl;
      }
      
          std::array<int,2> a{1,2};
          std::vector<int> v{1,2,3};
          std::list<double> l{2., 3., 5.4};
          std::map<int,double> m{ {1,2.},{10,3.14} };
          std::multimap<int,int> m2{ {2,3},{4,5} };
          std::set<float> s{1.f, 23.f, 2.f};
          std::unordered_map<int,Foo> m3{ {1,Foo(1)}, {2,Foo(2)}, {3,Foo(3)}}; 
          PrintCont(a);
          PrintCont(v);
          PrintCont(l);
          PrintCont(m);
          PrintCont(a);
          PrintCont(s);
          PrintCont(m2);
          PrintCont(m3);
      

      Live demo

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-23
        • 1970-01-01
        • 1970-01-01
        • 2017-04-14
        • 2010-12-02
        相关资源
        最近更新 更多