如何在编译期判断某类型是否为特定模板的实例化?
编译期判断类型是否为特定模板的实例化(含非类型参数模板)
你的问题核心在于原代码的模板只能匹配所有参数都是类型的模板(比如std::vector、std::queue),但像std::array这种包含非类型模板参数(第二个参数是size_t常量)的模板,原有的template<typename...> class模板参数无法匹配它的签名。
用C++17引入的auto模板参数就能完美解决这个问题,它允许我们匹配任意类型的模板参数(类型、非类型都可以)。修改后的代码如下:
#include <iostream> #include <type_traits> #include <vector> #include <array> #include <queue> // 主模板:默认判定为不是目标模板的实例化 template<template<auto...> class, typename> struct is_instantiation : std::false_type {}; // 特化匹配:当第二个类型是第一个模板的实例化时,返回true template<template<auto...> class U, auto... Args> struct is_instantiation<U, U<Args...>> : std::true_type {}; // 封装成变量模板,简化使用 template<template<auto...> class U, typename T> constexpr bool is_instantiation_v = is_instantiation<U, T>::value; int main() { using VecInt = std::vector<int>; using ArrInt5 = std::array<int, 5>; std::cout << std::boolalpha; // 输出true/false而不是1/0,更直观 std::cout << "std::vector<int> 是 std::vector 的实例化? " << is_instantiation_v<std::vector, VecInt> << "\n"; std::cout << "std::vector<int> 是 std::queue 的实例化? " << is_instantiation_v<std::queue, VecInt> << "\n"; std::cout << "std::array<int,5> 是 std::array 的实例化? " << is_instantiation_v<std::array, ArrInt5> << "\n"; }
关键修改点说明:
- 把原模板的
template<typename...> class改成template<auto...> class:这样模板参数U可以匹配任何模板,不管它的参数是类型(比如std::vector的typename T)、非类型(比如std::array的size_t N),甚至C++20的模板模板参数。 - 特化部分的
auto... Args会捕获目标模板实例化时的所有参数,不管它们的类型,完美适配不同签名的模板。 - 新增的
is_instantiation_v变量模板是语法糖,让我们不用每次都写::value,代码更简洁。
这个方案不仅能处理你提到的std::vector和std::array,像std::map<int, std::string>这种多类型参数的模板、std::bitset<16>这种纯非类型参数的模板,都能正确判断。
内容的提问来源于stack exchange,提问作者R zu
相关产品推荐
相关产品推荐

