Jan*_*net 40 c++ templates template-templates variadic-templates c++11
我想知道是否可以编写一个模板函数,可以将任何其他任意模板作为参数并正确匹配模板名称(即不仅仅是结果类).我所知道的工作是:
template<template<typename ...> class TemplateT, typename... TemplateP>
void f(const TemplateT<TemplateP...>& param);
Run Code Online (Sandbox Code Playgroud)
这将匹配例如用于f(std::vector<int>())或f(std::list<int>())但不会对工作f(std::array<int, 3>()),作为第二个参数是一个size_t无类型.
现在我想我可以做一些疯狂的事情:
template<template<typename ...> class TemplateT, size... Sizes, typename... TemplateP>
void f(const TemplateT<Sizes..., TemplateP...>& param);
Run Code Online (Sandbox Code Playgroud)
希望编译器能够正确地将TemplateP省略号或Sizes省略号导出为空.但它不仅难看,它仍然适用于采用任何类型或size_t参数的模板.它仍然不会匹配任意模板,例如bool参数.
对于重载方法也是如此:
template<template<typename ...> class TemplateT, typename... TemplateP>
void f(const TemplateT<TemplateP...>& param);
template<template<typename ...> class TemplateT, size... Sizes>
void f(const TemplateT<Sizes...>& param);
Run Code Online (Sandbox Code Playgroud)
此外,这种方法不会"工作,如果我们想混size_t和typenames.那么匹配任何内容所需要的就是这样的东西,其中对省略号中允许的内容没有任何限制:
template<template<...> class TemplateT, ... Anything>
void f(const TemplateT<Anything...>& param);
Run Code Online (Sandbox Code Playgroud)
该语法不起作用,但也许还有其他语法来定义这样的东西?
这主要是我想知道该语言有什么可能,认为它可能实际上有用,如果你有不同的模板,其中第一个参数总是被修复,你想根据返回类型更改它并保留其他所有内容.像这样的东西:
template<
template<typename ValueT, ...> class TemplateT,
... Anything,
typename ValueT,
typename ResultT = decltype(some_operation_on_value_t(std::declval<ValueT>())>
TemplateT<ResultT, Anything...> f(const TemplateT<ValueT, Anything...>& in);
Run Code Online (Sandbox Code Playgroud)
那么,使用模式匹配以任何方式使这个工作以完全通用的方式工作?
这不仅仅是一个思想实验,因为我遇到的用例就是创建在容器上运行的纯函数原语,并隐式构造不可变的结果容器.如果结果容器具有不同的数据类型,我们需要知道容器操作的类型,因此对任何容器的唯一要求是模板的第一个参数需要是输入类型,因此可以用不同的替换结果中的输出类型,但代码应该忽略之后的任何模板参数,并且不应该关心它是类型还是值.
您必须有一个重新绑定容器类型的元函数。因为你不能只替换第一个模板参数:
vector<int, allocator<int> > input;
vector<double, allocator<int> > just_replaced;
vector<double, allocator<double> > properly_rebound;
Run Code Online (Sandbox Code Playgroud)
因此,只需为已知的一组容器编写这样的元函数即可。
template<class Container, class NewValue> class rebinder;
// example for vectors with standard allocator
template<class V, class T> class rebinder< std::vector<V>, T > {
public:
typedef std::vector<T> type;
};
// example for lists with arbitrary allocator
template<class V, class A, class T> class rebinder< std::list<V,A>, T > {
typedef typename A::template rebind<T>::other AT; // rebind the allocator
public:
typedef std::list<T,AT> type; // rebind the list
};
// example for arrays
template<class V, size_t N> class rebinder< std::array<V,N>, T > {
public:
typedef std::array<T,N> type;
};
Run Code Online (Sandbox Code Playgroud)
不同容器的重新绑定规则可能有所不同。
此外,您可能需要一个从任意容器中提取值类型的元函数,而不仅仅是符合 std 的 ( typedef *unspecified* value_type)
template<class Container> class get_value_type {
public:
typedef typename Container::value_type type; // common implementation
};
template<class X> class get_value_type< YourTrickyContainer<X> > {
......
public:
typedef YZ type;
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2591 次 |
| 最近记录: |