C++ 理解元函数在类型包中查找类型

C++ 理解元函数在类型包中查找类型,c++,templates,C++,Templates,需要帮助才能理解代码 我试图理解这段代码,它用于查找我们传递的类型是否存在于其余参数中。 例如,在下面的代码中,我试图找出我所传递的其余类型中是否存在char。 现在我无法理解这段代码是如何返回我与其他类型一起传递的类型的索引的 包括 包括 命名空间id按类型详细信息列出{ 样板 结构id_by_类型:std::integral_常量{}; 样板 结构id_by_type:id_by_type{}; 样板 结构id_by_类型:std::integral_常量{}; }//名称空间id按类型详细

需要帮助才能理解代码

我试图理解这段代码,它用于查找我们传递的类型是否存在于其余参数中。 例如,在下面的代码中,我试图找出我所传递的其余类型中是否存在char。 现在我无法理解这段代码是如何返回我与其他类型一起传递的类型的索引的

包括 包括 命名空间id按类型详细信息列出{ 样板 结构id_by_类型:std::integral_常量{}; 样板 结构id_by_type:id_by_type{}; 样板 结构id_by_类型:std::integral_常量{}; }//名称空间id按类型详细信息列出 样板 使用typeid\u v=id\u by\u type\u detail::id\u by\u type; 样板 结构包含_v:std::conditional::type{}; int main{ std::size\u t a=typeid\u v::value; 我试着解释一下

std::size_t a = typeid_v<char, bool, char, int, float, double>::value;
是最通用的。如果没有匹配的类型,它将终止递归。 它定义了一个具有一个成员size\u t value=I;的结构

第二个模板实际上是第一个模板的部分专门化

template <std::size_t I, typename T, typename U, typename... Args>
struct id_by_type<I, T, U, Args...> : id_by_type<I + 1, T, Args...> {};
template <std::size_t I, typename T, typename... Args>
struct id_by_type<I, T, T, Args...> : std::integral_constant<std::size_t, I> {};
是最特殊的。如果第二个模板参数 第三个模板参数将具有相同的类型。与第一个模板一样,它定义了一个成员大小为I;的结构

最后缺失的部分是

template <typename T, typename... Args>
using typeid_v = id_by_type_detail::id_by_type<0, T, Args...>;
这件事已经解决了

typeid_v<char, bool, char, int, float, double>::value
typeid_v<short, bool, char, int>::value
导致

size_t a = 1;
std::cout << 3 << '\n';
不在列表中的类型的另一个示例:

std::cout << typeid_v<short, bool, char, int>::value << '\n';
导致

size_t a = 1;
std::cout << 3 << '\n';
据我所知,超出范围的结果表示在列表中找不到该类型

template <typename T, typename... Args>
struct contains_v : std::conditional<typeid_v<T, Args...>::value == sizeof...(Args), std::false_type, std::true_type>::type {};

证明我是对的。

让我们先看看默认模板:

template <std::size_t I, typename... Args>
struct id_by_type : std::integral_constant<std::size_t, I> {};
那么,这是一个怎样的迭代呢

id_by_类型是从自身继承的,但它不是一个无限递归。它是一个有限递归,因为我们用不同的参数继承这个类

//                 |---- Search again
//  Search ---v    v     v------- Rest...
id_by_type<I, int, int, char, float> : std::integral_constant<std::size_t, I>
有多大不同?第一个参数没有发送

然后,对于它的下一个实例化,First从Rest的第一个元素中提取,我们还增加了计数器I

因此,这个特定的实例化如下所示:

//                 |---- First
//  Search ---v    v     v------- Rest...
id_by_type<1, int, char, float, int> : id_by_type<2, int, float, int>
auto id_by_type(std::size_t I, type Search, type First, type[] Rest) -> std::size_t {
    if (Search == First) {
        // found specialization, return I
        return I;
    } else if (!Rest.empty()) {
        // iteration specialization, increment and drop first
        return id_by_type(I + 1, Search, Rest.first(), Rest.drop_first());
    } else {
        // primary template, type not found
        return I + 1;
    }
}
那么,什么时候选择这个专门化呢?好吧,只有当我们能够将搜索与前两个参数匹配时

//                 |---- Search again
//  Search ---v    v     v------- Rest...
id_by_type<I, int, int, char, float> : std::integral_constant<std::size_t, I>

是否有一个特定的东西,你不理解的代码?解释这个片段中使用的每一个语言特征会花费太多的时间。你碰到了这个你试图解决的代码的问题吗?我对C++模板是新的,所以如果你能至少帮助一些与这个代码块相关的参考或主题,这可以帮助我理解这一点。HolyBlackCat@GuillaumeRacicot我试图在模板中编写一段代码,它可以帮助我发现类型是否存在。虽然它工作正常,但不是由我编写的,现在我正在尝试理解这段代码到底是什么以及如何执行的。@Piyusvijay是否有您需要帮助理解的特定部分?是吗::value==sizeof…Args或id_by_类型的专用方式?我将尝试澄清问题并重新打开它。
id_by_type_detail::typeid_v<3, short>::value
std::integral_constant<size_t, 3>
struct {
  size_t value = 3;
  /// and some extra stuff
};
std::cout << 3 << '\n';
template <typename T, typename... Args>
struct contains_v : std::conditional<typeid_v<T, Args...>::value == sizeof...(Args), std::false_type, std::true_type>::type {};
template <std::size_t I, typename... Args>
struct id_by_type : std::integral_constant<std::size_t, I> {};
template <std::size_t I, typename T, typename U, typename... Args>
struct id_by_type<I, T, U, Args...> : id_by_type<I + 1, T, Args...> {};
template <std::size_t I, typename Search, typename First, typename... Rest>
struct id_by_type<I, Search, First, Rest...> : id_by_type<I + 1, Search, Rest...> {};
//                 |---- First
//  Search ---v    v     v------- Rest...
id_by_type<1, int, char, float, int> : id_by_type<2, int, float, int>
template <std::size_t I, typename Search, typename... Rest>
struct id_by_type<I, Search, Search, Rest...> : std::integral_constant<std::size_t, I> {};
//                 |---- Search again
//  Search ---v    v     v------- Rest...
id_by_type<I, int, int, char, float> : std::integral_constant<std::size_t, I>
auto id_by_type(std::size_t I, type Search, type First, type[] Rest) -> std::size_t {
    if (Search == First) {
        // found specialization, return I
        return I;
    } else if (!Rest.empty()) {
        // iteration specialization, increment and drop first
        return id_by_type(I + 1, Search, Rest.first(), Rest.drop_first());
    } else {
        // primary template, type not found
        return I + 1;
    }
}