如何在模板函数中实现模板类类型?

nic*_*ick 2 c++ templates c++-standard-library function-templates c++17

我想为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 
    {  }
}
Run Code Online (Sandbox Code Playgroud)

我认为问题发生在 istype()

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

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

JeJ*_*eJo 5

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

对于像搁浅容器这样的模板类,您需要指定模板参数以获取具体类型,然后您可以使用std::is_same. 这意味着像std::is_same_v<T, std::vector<int>>orstd::is_same_v<T, std::vector<float>>等...会起作用。

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

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

见演示

#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);
}
Run Code Online (Sandbox Code Playgroud)