具有多个包的参数包匹配规则
Parameter Pack Matching Rules with Multiple Packs
我正在尝试编写一个函数,该函数使用参数包和一些标准匹配规则来获取另一个函数。举个例子:
template <typename... TListElems, typename... TVectorElems>
void goal(void (*fn)(std::list<TListElems>..., std::vector<TVectorElems>...));
为了消除TListElems
和TVectorElems
的歧义,我添加了一些std::tuple<T...>*
以便调用者可以显式
template <typename... TListElems, typename... TVectorElems>
void foo(std::tuple<TListElems...>*,
std::tuple<TVectorElems...>*,
void (*)(std::list<TListElems>..., std::vector<TVectorElems>...))
{
// blah blah blah
}
void bar(std::list<int>, std::list<unsigned>, std::vector<float>, std::vector<double>)
{
// blah blah blah
}
int main()
{
foo((std::tuple<int, unsigned>*) nullptr,
(std::tuple<float, double>*) nullptr,
&bar);
}
Clang很高兴地以我期望的方式编译它,而g++(7.2.1)给出了编译错误:
matching.cpp: In function ‘int main()’:
matching.cpp:20:13: error: no matching function for call to ‘foo(std::tuple<int, unsigned int>*, std::tuple<float, double>*, void (*)(std::list<int>, std::list<unsigned int>, std::vector<float>, std::vector<double>))’
&bar);
^
matching.cpp:6:6: note: candidate: template<class ... TListElems, class ... TVectorElems> void foo(std::tuple<_Tps ...>*, std::tuple<_Elements ...>*, void (*)(std::list<TListElems>..., std::vector<TVectorElems>...))
void foo(std::tuple<TListElems...>*,
^~~
matching.cpp:6:6: note: template argument deduction/substitution failed:
matching.cpp:20:13: note: mismatched types ‘std::vector<TVectorElems>’ and ‘std::list<int>’
&bar);
^
在main
中,我希望对foo
的调用推断出TListElems
<int, unsigned>
和TVectorElems
为<float, double>
,导致fn
属于void (*)(std::list<int>, std::list<unsigned>, std::vector<float>, std::vector<double>)
类型(当只有一个包或我手动编写重载时的操作方式)。
§14.8.2.5/10 是标准最接近明确阻止foo
示例起作用的:
[注意:函数参数包只能出现在参数声明列表(8.3.5)的末尾。
std::list<TListElems>...
一点fn
似乎违反了这个笔记,但这并不完全清楚。
问题是:谁是对的?海湾合作委员会、叮当还是别的什么?
我认为clang就在这里。
在void (*)(std::list<TListElems>..., std::vector<TVectorElems>...)
中,TListElems...
是一个非演绎的语境,这使得TVectorElems...
也是一个非演绎的语境。但是这两个参数包都可以从两个元组指针参数中推导,并且预计它也可以在这里使用该推导结果。
我提交了 gcc 错误 83542。
你可以让两个编译器都对不可推导类型感到满意:
template <typename T>
struct non_deducible {
using type = T;
};
template <typename T> using non_deducible_t = typename non_deducible<T>::type;
template <typename... TListElems, typename... TVectorElems>
void foo(std::tuple<TListElems...>*,
std::tuple<TVectorElems...>*,
void (*)(non_deducible_t<std::list<TListElems>>...,
non_deducible_t<std::vector<TVectorElems>>...))
{
// blah blah blah
}
演示
- 如何反转整数参数包
- 如何将enable-if与模板参数和参数包一起使用
- 模板元编程:如何将参数包组合成新的参数包
- 模板参数推导失败,函数参数/参数不匹配
- 错误 没有与参数列表匹配的重载函数"getline"实例
- C ++:在构造函数中使用参数包?
- 如何使我的 sizeof sum 结构与空参数包一起工作
- std::vector 没有重载函数的实例与参数列表匹配
- 双模板参数包
- 参数包构造函数在类模板中隐藏用户定义的转换
- 嵌套参数包扩展失败
- 参数包中的筛选器类型
- 参数和参数包的类型推导
- 为模板参数包添加别名
- enable_if中参数包的大小问题
- 具有先前参数类型匹配的参数包
- 有没有办法部分匹配可变参数模板参数包?
- 如何根据模板参数包是否匹配函数参数来控制模板函数定义?
- 演绎指南和具有可变参数模板构造函数的可变参数类模板 - 参数包长度不匹配
- 具有多个包的参数包匹配规则