【发布时间】:2020-12-23 11:39:06
【问题描述】:
我正在阅读 spconv 的源代码,这是一个由 c++(和 cuda)编写的稀疏卷积库,在源代码中我发现了一个复杂的模板用法,我将其总结为下面的最小工作示例:
#include <iostream>
#include <sstream>
template<class... T>
struct mp_list {
};
template<class T, T... I> using mp_list_c = mp_list<std::integral_constant<T, I>...>;
template<class... Ts, class F>
constexpr F mp_for_each_impl(mp_list<Ts...>, F &&f) {
return (void) (std::initializer_list<int>{(f(Ts()), 0)...}), std::forward<F>(f);
}
template<class A, template<class...> class B>
struct mp_rename_impl {
};
template<template<class...> class A, class... T,
template<class...> class B>
struct mp_rename_impl<A<T...>, B> {
using type = B<T...>;
};
template<class A, template<class...> class B> using mp_rename = typename mp_rename_impl<A, B>::type;
template<class L, class F>
constexpr F mp_for_each(F &&f) {
return mp_for_each_impl(mp_rename<L, mp_list>(), std::forward<F>(f));
}
template<int... Is, typename F>
bool dispatch_int_noexcept(int idx, F &&f) {
static_assert(sizeof...(Is) > 0, "you need to provide at least one candidate");
bool notFound = true;
mp_for_each<mp_list_c<int, Is...>>([=, ¬Found, &f, &idx](auto I) {
if (decltype(I)::value == idx && notFound) {
std::forward<F>(f)(I);
notFound = false;
}
});
return !notFound;
}
template<int ... Is, typename F>
void dispatch_int(int idx, F &&f) {
if (!dispatch_int_noexcept<Is...>(idx, std::forward<F>(f))) {
std::stringstream ss;
mp_for_each<mp_list_c<int, Is...>>([=, &ss](auto I) { ss << decltype(I)::value << " "; });
std::cout << "unknown value " << idx << ", available: " << ss.str() << std::endl;
}
}
int main() {
int ndim;
std::cin >> ndim;
dispatch_int<2, 3, 4>(ndim, [&](auto I) {
constexpr int NDim = decltype(I)::value;
std::cout << "using ndim= " << NDim << std::endl;
// blablabla ... ...
});
return 0;
}
在main()中,函数dispatch_int<2, 3, 4>(ndim, [&](auto I) {})接收一个参数ndim,并检查ndim是否在预定义列表<2, 3, 4>中,如果是,则执行以下使用特定@987654329编译的代码@。
但是,我无法理解它是如何工作的,上面定义的模板真的很混乱。经过大量搜索,我猜这是一种模板元编程来分派参数,但仍然无法弄清楚细节,谁能解释一下上面的代码是如何工作的?
【问题讨论】:
-
不清楚您不了解其中的哪一部分。你发布了大约 50 行代码,你不能指望我们详细解释每一行。请点具体代码sn-ps。
-
可能使用模板预处理器工具,例如这里建议的工具? stackoverflow.com/questions/1139793/…
-
我相信你会因为阅读这样的代码而感到沮丧。但是除了学习模板语法和语义之外别无他法。它并不像第一次看到的那么难!诸如“哪个实例最适合”或类型推断之类的一些细节可能很难,但这不是此处发布的代码中的问题!
标签: c++ templates metaprogramming