Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;参数分派的模板元编程 我读了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...>>([=, &notFound, &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; } #包括 #包括 模板 结构mp_列表{ }; 使用mp_列表的模板c=mp_列表; 模板 每个impl的常量表达式F mp_(mp_列表,F&&F){ return(void)(std::initializer_list{(f(Ts()),0)…}),std::forward(f); } 模板 结构mp\u重命名\u impl{ }; 模板 结构mp\u重命名\u impl{ 使用类型=B; }; 模板使用mp\u rename=typename mp\u rename\u impl::type; 模板 每个(F&F)的常量表达式F mp_{ 返回mp_for_each_impl(mp_rename(),std::forward(f)); } 模板 bool调度\u int\u noexcept(int idx、F和F){ static_assert(sizeof…(Is)>0,“您需要提供至少一个候选者”); bool notFound=true; 每个([=,¬Found,&f,&idx](自动I)的mp_{ if(decltype(I)::value==idx&¬Found){ 标准:远期(f)(I); notFound=false; } }); 返回!未找到; } 模板 无效调度(int idx、F和F){ 如果(!dispatch_int_noexcept(idx,std::forward(f))){ std::stringstream-ss; mp_for_each([=,&ss](自动I){ss_C++_Templates_Metaprogramming - Fatal编程技术网

C++;参数分派的模板元编程 我读了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...>>([=, &notFound, &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; } #包括 #包括 模板 结构mp_列表{ }; 使用mp_列表的模板c=mp_列表; 模板 每个impl的常量表达式F mp_(mp_列表,F&&F){ return(void)(std::initializer_list{(f(Ts()),0)…}),std::forward(f); } 模板 结构mp\u重命名\u impl{ }; 模板 结构mp\u重命名\u impl{ 使用类型=B; }; 模板使用mp\u rename=typename mp\u rename\u impl::type; 模板 每个(F&F)的常量表达式F mp_{ 返回mp_for_each_impl(mp_rename(),std::forward(f)); } 模板 bool调度\u int\u noexcept(int idx、F和F){ static_assert(sizeof…(Is)>0,“您需要提供至少一个候选者”); bool notFound=true; 每个([=,¬Found,&f,&idx](自动I)的mp_{ if(decltype(I)::value==idx&¬Found){ 标准:远期(f)(I); notFound=false; } }); 返回!未找到; } 模板 无效调度(int idx、F和F){ 如果(!dispatch_int_noexcept(idx,std::forward(f))){ std::stringstream-ss; mp_for_each([=,&ss](自动I){ss

C++;参数分派的模板元编程 我读了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...>>([=, &notFound, &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; } #包括 #包括 模板 结构mp_列表{ }; 使用mp_列表的模板c=mp_列表; 模板 每个impl的常量表达式F mp_(mp_列表,F&&F){ return(void)(std::initializer_list{(f(Ts()),0)…}),std::forward(f); } 模板 结构mp\u重命名\u impl{ }; 模板 结构mp\u重命名\u impl{ 使用类型=B; }; 模板使用mp\u rename=typename mp\u rename\u impl::type; 模板 每个(F&F)的常量表达式F mp_{ 返回mp_for_each_impl(mp_rename(),std::forward(f)); } 模板 bool调度\u int\u noexcept(int idx、F和F){ static_assert(sizeof…(Is)>0,“您需要提供至少一个候选者”); bool notFound=true; 每个([=,¬Found,&f,&idx](自动I)的mp_{ if(decltype(I)::value==idx&¬Found){ 标准:远期(f)(I); notFound=false; } }); 返回!未找到; } 模板 无效调度(int idx、F和F){ 如果(!dispatch_int_noexcept(idx,std::forward(f))){ std::stringstream-ss; mp_for_each([=,&ss](自动I){ss,c++,templates,metaprogramming,C++,Templates,Metaprogramming,所以第一部分(减去无用部分) 此外,mp_rename用于泛型,因为mp_for_each_implusemp_list重命名用于将“具有可变模板的任何类型”转换为mp_list 然后在: template<int ... Is, typename F> void dispatch_int(int idx, F &&f) { if (!dispatch_int_noexcept<Is...>(idx, std::forward<F>(f

所以第一部分(减去无用部分)

此外,
mp_rename
用于泛型,因为
mp_for_each_impl
use
mp_list
重命名用于将“具有可变模板的任何类型”转换为
mp_list

然后在:

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 idx、F和F){
如果(!dispatch_int_noexcept(idx,std::forward(f))){
std::stringstream-ss;

每个([=,&ss](自动I)的mp_{ss不清楚您不了解其中的哪一部分。您发布了大约50行代码,您不能期望我们详细解释每一行。请指出具体的代码片段。可能使用此处建议的模板预处理工具?我相信您可能会对阅读此类代码感到失望。但没有其他w比学习模板语法和语义还难。这并不像第一次看到的那么难!一些细节,如“哪个实例最适合”或者类型推断可能很难,但这不是这里发布的代码中的问题!我不是!我看不到任何解释行…解释在注释中。我没有为每个
进入
mp\u,它的名称意味着要求解释变量模板魔术如何工作…你的解释是非常非常非常顶级的我有添加和解释核心代码,删除无用的返回和rename@rhaport更好?
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<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;
    }
}
template<int... Is, typename F>
bool dispatch_int_noexcept(int idx, F &&f) {
    // just a check
    static_assert(sizeof...(Is) > 0, "you need to provide at least one candidate");
    bool notFound = true;
    mp_for_each<mp_list_c<int, Is...>>([=, &notFound, &f, &idx](auto I) {
        // look if the 'ndim' match one of the ints of dispatch_int<2, 3, 4>
        // note they are now std::integral_constant, so ::value
        if (decltype(I)::value == idx && notFound) {
            // found : call the early lambda with the integral_constant
            // that why you do the 'constexpr int NDim = decltype(I)::value;'
            std::forward<F>(f)(I);
            notFound = false;
        }
    });
    return !notFound;
}