【问题标题】:Is it possible to capture a type template into a template argument?是否可以将类型模板捕获到模板参数中?
【发布时间】:2021-10-14 18:12:14
【问题描述】:

是否可以从模板参数中捕获模板,即有一个嵌套的模板说明符和一个包含模板类型的模板参数?

template< typename T, typename Label = std::string>
class foo {
    // ...
};

template <
            template < typename C, typename T > typename C<T>,
            // ...
            typename Label = std::string
         >
class bar {
    // ...
    C< foo< T, Label > > A;
};

例如,我想传递一个通用 STL 容器 (std::vector&lt; int &gt;) 作为模板参数,但声明一个具有相同元类型 (std::vector) 但具有不同值类型 (foo&lt; int &gt;) 的成员即std::vector&lt; foo&lt; int &gt; &gt;。这可能看起来很复杂,但最好不要硬编码 STL 容器的类型。

就上下文而言,我的目标是提供一些更高级别的功能的通用容器适配器/包装器(在std::stackstd::queue 行中)。

【问题讨论】:

    标签: c++ templates generics stl containers


    【解决方案1】:

    是的,您可以只使用模板专业化:

    #include <string>
    
    template<typename T, typename Label = std::string>
    class foo {};
    
    template <class T, typename Label = std::string>
    class bar;
    
    template <template<class...> class C, typename T, typename Label>
    class bar<C<T>, Label> {
      C<foo<T, Label>> A;
    };
    

    Demo.

    【讨论】:

    • 为什么在模板中混合使用classtypename
    • @BotondHorváth - 我猜这是因为 (a) 它们是可互换的,并且 (b) 向用户发出信号,应该为给定的类类型提供什么参数才能使代码正常工作。
    • 这正是我想要的。但是,有没有办法为C 提供默认参数?
    • bar的第一个模板参数是type,不是template,表示已经实例化,所以没有为它提供默认参数是有意义的。
    【解决方案2】:

    另一个答案的方法可以概括为可重用的模板重新绑定器:

    template<typename T>
    struct rebinder;
    
    template<template<typename...> typename T, typename... Args>
    struct rebinder<T<Args...>> {
      template<typename... Us>
      using rebind = T<Us...>;
    };
    
    template<typename T, typename... Us>
    using rebound = rebinder<T>::template rebind<Us...>;
    
    // example:
    #include <vector>
    
    template<typename T>
    struct MyStruct {
        rebound<T, float> vec;
    };
    
    int main() {
        MyStruct<std::vector<int>> x;
        static_assert(std::is_same_v<std::vector<float>, decltype(x.vec)>);
    }
    

    godbolt

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-31
      • 1970-01-01
      • 2014-01-29
      相关资源
      最近更新 更多