c++ - 模板模板参数的显式匹配
问题描述
考虑这个函数:
template<template<class, class> class C, class T, class Alloc>
void foo(C<T, Alloc>& container) {
std::cout << container.size() << std::endl;
}
函数foo()
接受 a std::vector<T, Alloc>
,但它std::map<Key, T, Compare, Allocator>
在 C++17 中也接受,因为Compare
和Allocator
具有默认值。笔记std::map
在 C++14 中失败。
我怎样才能foo()
只接受只有 2 个模板参数的模板,所以它std::map
在 C++17 中失败了?
解决方案
我怎样才能让 foo 只接受只有 2 个模板参数的模板,所以它在 C++17 中因 std::map 而失败?
如果您想避免foo()
接受接受三个或更多模板参数的容器(因此失败std::map
)相对简单:您可以遵循 rtpax 的建议,或者,给定一个自定义类型特征,说明一个类型是否基于两种类型的接受容器
template <typename>
struct accept2 : std::false_type
{ };
template <template <typename...> class C, typename X, typename Y>
struct accept2<C<X, Y>> : std::true_type
{ };
以及三接受容器的类似类型特征
template <typename>
struct accept3 : std::false_type
{ };
template <template <typename...> class C, typename X, typename Y, typename Z>
struct accept3<C<X, Y, Z>> : std::true_type
{ };
foo()
仅当推导的类型接受两种但不接受三种类型时,您才能启用 SFINAE
template <typename C>
std::enable_if_t<accept2<C>{} && !accept3<C>{}> foo (C const & container)
{ }
但是这个解决方案(以及 rtpax 解决方案)有一个问题:如果容器在两个模板类型之前和一个(或多个)具有默认值的模板非类型参数之后接收呢?
还是两种模板类型和一个(或多个)具有默认值的模板模板参数?也许有不同的签名?
您可以添加accept3
特化来识别其他情况,但类型、非类型和模板模板参数的无限组合,在前两个模板类型之后具有默认值。所以你必须编写无限特化来拦截所有情况。
这有点不切实际。
而且我怀疑(在 C++17 中)没有实用的解决方案。
无论如何,一个完整的编译示例(避免三个或更多模板类型容器)如下
#include <map>
#include <vector>
#include <type_traits>
template <typename>
struct accept2 : std::false_type
{ };
template <template <typename...> class C, typename X, typename Y>
struct accept2<C<X, Y>> : std::true_type
{ };
template <typename>
struct accept3 : std::false_type
{ };
template <template <typename...> class C, typename X, typename Y, typename Z>
struct accept3<C<X, Y, Z>> : std::true_type
{ };
template <typename C>
std::enable_if_t<accept2<C>{} && !accept3<C>{}> foo (C const &)
{ }
int main()
{
std::vector<int> v;
std::map<int,int> m;
foo(v); // compile
//foo(m); // compilation error
}
推荐阅读
- javascript - Javascript选择具有最多项目的向量
- html - 为什么这个 Ruby on Rails 程序给我一个语法错误?
- javascript - npm run-script ssr(服务器端渲染不工作)
- excel - 如何根据 VBA 中的活动行选择范围?
- php - PHP 构造函数调用自身 - 不是递归
- c - “getchar()”如何知道在 C 中要读取什么字符?
- julia - 为什么在 Julia 中不鼓励使用下划线?
- html - 如何让我的网站元素自动适应屏幕尺寸?
- vba - 如何使用 VBA 删除 powerpoint 文件中的所有嵌入视频?
- python - 从一系列条件中检查是否还有