简体   繁体   English

如何在C ++中使用带有模板的类型作为模板参数

[英]How to use a type with template as a template parameter in C++

I'm trying to use different types of containers of different types with the same function but couldn't convince my compiler. 我正在尝试使用具有相同功能的不同类型的不同类型的容器,但无法说服我的编译器。 Here are some of the things I have tried: 以下是我尝试过的一些事情:

#include <iostream>
#include <vector>
#include <list>
using namespace std;

// error: expected a qualified name after 'typename'
template<typename C<T>>
void func1() {
  C<T> c;
  c.push_back(new T);
}

// error: expected a qualified name after 'typename'
template<typename C<typename T>>
void func2() {
  C<T> c;
  c.push_back(new T);
}

// error: expected a qualified name after 'typename'
template<typename C<template <typename T>>>
void func3() {
  C<T> c;
  c.push_back(new T);
}

int main(int argc, char *argv[]) {
  func1<vector<int>>();
  func1<list<float>>();

  func2<vector<int>>();
  func2<list<float>>();

  func3<vector<int>>();
  func3<list<float>>();
  return 0;
}

Is this possible in C++? 这在C ++中是否可行?

The closest I think you can get to your original code (assuming you wanted two parameters, C and T and not just one C<T> ) is the following: 最接近我认为你可以得到你的原始代码(假设你想要两个参数, CT而不只是一个C<T> )如下:

#include <iostream>
#include <vector>
#include <list>
using namespace std;

template<template< class T, class A = allocator<T> > class C, typename T>
void func() {
  C<T*> c;
  c.push_back(new T);
}

int main(int argc, char *argv[]) {
  func<vector, int>();
  func<list, float>();
  return 0;
}

Notice two things: 注意两件事:

  1. The vector and list templates take two parameters, the second one defaulting to allocator<T> (where T is the first parameter). vectorlist模板有两个参数,第二个参数默认为allocator<T> (其中T是第一个参数)。 You cannot define the template with just one parameter; 您不能只使用一个参数定义模板; the type system will complain when instantiating. 类型系统在实例化时会抱怨。

  2. If you have a container of type C<T> with a push_back method expecting a T (like vector and list ), you cannot pass it new T as a parameter. 如果你有一个C<T>类型的容器,并且push_back方法需要一个T (比如vectorlist ),你就不能将new T作为参数传递给它。 I took the liberty of fixing the container to be of type C<T*> . 我冒昧地将容器固定为C<T*>类型。

I think you are talking about "template template parameters" . 我想你在谈论“模板模板参数”

Template-template parameters are a kind of type template parameters which template classes are allowed only. 模板模板参数是一种类型模板参数,仅允许模板类。 That class template could have any kind of template parameters. 该类模板可以具有任何类型的模板参数。 For example: 例如:

template<template<typename T , typename ALLOCATOR> class CONTAINER>
void func2()
{
    CONTAINER<T,ALLOCATOR> container;

    container.push_back( T() );
} 

int main()
{
    func2<std::vector<bool>>();
}

This is useful when you need to extract the template parameters of a class template which you have passed as template parameter. 当您需要提取已作为模板参数传递的类模板的模板参数时,这非常有用。
Checkout this question for more info. 查看此问题以获取更多信息。

On the other hand, as chris noticed in his answer, in your case its easier to pass a type parameter and suppose that type has a member type value_type , which is used to get the type of the elements of the container. 另一方面,正如克里斯在他的回答中所注意到的,在你的情况下,更容易传递一个类型参数,并假设该类型具有成员类型value_type ,用于获取容器元素的类型。

From your calls, I suspect you just want something like this (I'll make the code as close to what you have as possible and keep it C++03): 从你的电话中,我怀疑你只是想要这样的东西(我会让代码尽可能接近你所拥有的并保持C ++ 03):

template<typename T>
void func1() {
    T t;
    t.push_back(typename T::value_type());
}

typename expects a type - any type - and that's what it gets with vector<int> , list<float> , etc. On the other hand, vector by itself is just a template, not a type on its own. typename需要一个类型 - 任何类型 - 这就是它用vector<int>list<float>等得到的东西。另一方面, vector本身只是一个模板,而不是一个类型。 That's when you would need template<template<...> class> syntax. 那时你需要template<template<...> class>语法。

Do note, however, that trying to group containers like this often won't work because not every container supports the same operations as others. 但请注意,尝试对此类容器进行分组通常不起作用,因为并非每个容器都支持与其他容器相同的操作。 If you need an interface like this, you'll have to differentiate sequence containers, associative containers, etc. 如果你需要这样的接口,你必须区分序列容器,关联容器等。

first of all new will return a pointer, so the containers will not accept this, change that line, also you could do the following: 首先new会返回一个指针,所以容器不接受这个,改变那一行,你也可以做以下事情:

template<typename Container, typename T >
void func1() {
  Container c;
  c.push_back(T());
}

and in the main function: 并在主要功能:

func1<std::vector<int>, int >();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM