【问题标题】:Nested C++ template parameters for functions函数的嵌套 C++ 模板参数
【发布时间】:2013-12-20 19:51:24
【问题描述】:

我想在 C++ 中有一个模板函数,其中一个模板参数本身就是另一个模板参数的模板。如果这没有任何意义,请使用以下代码打印在类型 T 上模板化的 std::vector

template <typename T>
void print_vector(std::vector<T> &vec)
{
    for(auto v: vec)
        std::cout << v << " ";
    std::cout << std::endl;
}
...
std::vector<double> vec(5);
...
print_vector(vec);

我想将这个函数进一步推广到STL 容器而不是vector。但我不知道如何“嵌套”模板参数,以便容器在类型 T 上进行模板化。我尝试了以下但没有成功

template <typename T, template <typename TT> V>
void print_container(V<T> &con)
{
    for(auto c: con)
        std::cout << c << " ";
    std::cout << std::endl;
}
...
std::vector<double> vec(5);
...
print_container(vec);

我确定以前这里已经回答过这个问题,但是我找不到搜索词来找到答案。


感谢@ForEveR。你的回答是对的!对我的问题的所有回答都表明,没有必要将“存储”类型 T 模板化,以下解决方案足以满足我给出的示例:

template <typename C>
void print_container(C &con)
{
    for(auto v: con)
        std::cout << v << " ";
    std::cout << std::endl;
}

不幸的是,引发这个问题的实际用例有点复杂。该例程采用多个容器,例如这个带有矩阵和向量类的线性代数示例:

template <typename MATRIX, typename VECTOR>
void mat_vec_multiply(const MATRIX &A, const VECTOR &x, VECTOR &y)
{
    // Implement y = A*x;
}

假设 MATRIX 和 VECTOR 类都必须在相同的底层存储类(即doublefloatint 等)上进行模板化。这个想法是,通过显式指定 T 作为模板参数,我们可以强制执行:

template < typename T,
           template<typename> class MATRIX,
           template<typename> class VECTOR>
void mat_vec_multiply(const MATRIX<T> &A, const VECTOR<T> &x, VECTOR<T> &y)
{
    // Implement y = A*x;
}

不幸的是,我使用的是 CUDA 编译器 nvcc,它不支持 C++11 构造(我在示例中只使用了 C++11,因为它不那么冗长)。所以我不能使用std::is_samestatic_assert,尽管我想我可以很容易地推出自己的is_same(或使用Boost)。在这种情况下,什么是“最佳实践”,我想为存储类强制使用通用模板参数?

【问题讨论】:

    标签: c++ templates c++11


    【解决方案1】:

    std::vector 有两个参数,类型和分配器。 试试这个

    template <typename T, typename Alloc, template <typename, typename> class V>
    void print_container(V<T, Alloc> &con)
    {
    }
    
    print_container(vec);
    

    这适用于vectorlist 等,但不适用于mapset

    但是,由于您使用auto,因此您可以使用 C++11,然后您可以这样做:

    template <typename T, template <typename, typename...> class V, typename... Args>
    void print_container(V<T, Args...> &con)
    

    template <template <typename, typename...> class V, typename... Args>
    void print_container(V<Args...> &con)
    

    当然最简单的方法是做类似的事情

    template<typename C>
    void print_container(C& con)
    

    可能通过一些检查来推断,C 确实是容器。

    template<typename C>
    auto print_container(C& con) -> decltype(con.begin(), void())
    

    【讨论】:

      【解决方案2】:

      你最好不要那样做;考虑只在容器上进行模板化

      template <typename C>
      void print_container(const C& container)
      {
      
          for(auto v: container)
              std::cout << v << " ";
          std::cout << std::endl;
      }
      

      如果需要函数中存储的类型,可以使用:`typedef typename C::value_type T;

      【讨论】:

        【解决方案3】:

        我不确定我是否理解你想要的,但你可以试试这个:

        template <typename V>
        void print_vector(V &vec)
        {
            for(auto v: vec)
                std::cout << v << " ";
            std::cout << std::endl;
        }
        ...
        std::vector<double> vec(5);
        ...
        print_vector(vec);
        

        这里的重点是,通常您不需要像 template &lt; template V&lt; typename T&gt; &gt; 这样的构造,因为整个模板 template V&lt; typename T&gt; 可以泛化为类型 V

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多