【问题标题】:Template parameters in C++ templatesC++ 模板中的模板参数
【发布时间】:2014-02-05 05:20:02
【问题描述】:

我正在尝试使用模板模板参数,类似于 herehere(以及许多其他地方)所做的。

#include <vector>

template<template<class> class A, class B>
void f(A<B> &value) {
}

int main() {
    std::vector<int> value;
    f<std::vector, int>(value);
}

但是

$ g++-4.8 -std=c++0x base64.cpp
base64.cpp: In function ‘int main()’:
base64.cpp:9:23: error: no matching function for call to ‘f(std::vector<int>&)’
  f<std::vector, int>(value);
                       ^
base64.cpp:9:23: note: candidate is:
base64.cpp:4:6: note: template<template<class> class H, class S> void f(const H<S>&)
 void f(H<S> &value) {

我错过了什么?

【问题讨论】:

  • std::vector 有多个模板参数,如果可以推断出模板参数(此处可以),则不应明确指定模板参数。
  • 直接拨打f(v)可以吗?
  • @anthony-arnold,不。 note: template argument deduction/substitution failed: error: wrong number of template arguments (2, should be 1)
  • @chris,去掉参数还是不行。

标签: c++ templates c++11 template-meta-programming


【解决方案1】:

很确定这就是您要查找的内容:

template<template<class, class...> class V, class T, class... Args>
void fn(V<T,Args...>& value)
{
    // use value here.
}

简单地调用为:

std::vector<int> v;
fn(v);

在你问之前,是的,你可以使用需要更多参数的模板(如std::map&lt;&gt; 等),只要确保Arg... 涵盖可选参数并指定你关心的强制性参数。如:

#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <unordered_map>
#include <cstdlib>

template< template<class, class...> class V, class T, class... Args>
void fn_seq(const V<T,Args...>& value)
{
    std::cout << __PRETTY_FUNCTION__ << '\n';
    // use value here.
}

template< template<class, class, class...> class C, class K, class V, class... Args>
void fn_assoc(const C<K,V,Args...>& value)
{
    // use value here.
    std::cout << __PRETTY_FUNCTION__ << '\n';
}

int main()
{
    std::vector<int> vec;
    fn_seq(vec);

    std::list<double> lst;
    fn_seq(lst);

    std::map<int, float> m;
    fn_assoc(m);

    std::unordered_map<long, long> um;
    fn_assoc(um);

    return EXIT_SUCCESS;
}

输出

void fn_seq(const V<T, Args...> &) [V = vector, T = int, Args = <std::__1::allocator<int>>]
void fn_seq(const V<T, Args...> &) [V = list, T = double, Args = <std::__1::allocator<double>>]
void fn_assoc(const C<K, V, Args...> &) [C = map, K = int, V = float, Args = <std::__1::less<int>, std::__1::allocator<std::__1::pair<const int, float> >>]
void fn_assoc(const C<K, V, Args...> &) [C = unordered_map, K = long, V = long, Args = <std::__1::hash<long>, std::__1::equal_to<long>, std::__1::allocator<std::__1::pair<const long, long> >>]

【讨论】:

    【解决方案2】:

    除了修改函数定义,你还可以做另一件事,即使用模板别名来适配std::vector

    #include <vector>
    #include<iostream>
    
    template< 
      template<class> class A, 
      class B
      >
    void f(A<B> &value) {
        for( auto & x : value ) {
          std::cout << x << std::endl;
        }
    }
    
    template< class T >
    using VectorAdapter = std::vector<T>;
    
    int main() {
        VectorAdapter<int> value {1, 2, 3};
        f(value);
    }
    

    【讨论】:

    • 虽然这可行,但它需要在调用站点使用更多代码并明确指定可以让编译器推断的模板参数(如@WhozCraig 的回答)。我可以看到的一个优点是,这是一种解决方法,以防您无法更改功能。还有其他我没有想到的专业人士吗?
    • @Agentlien 我添加了答案正是因为有时您无法更改函数声明。关于“明确指定模板参数”见编辑。
    【解决方案3】:

    Vector 有 2 个模板参数,(第二个几乎从未使用过,并且有一个默认的分配器类型)

    template < class T, class Alloc = allocator<T> > class vector;
    

    应该是这样的:

    template<template<class,class> class H, class S,class A>
    void f(const H<S,A> &value) {
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-01
      相关资源
      最近更新 更多