【发布时间】:2018-06-04 15:01:07
【问题描述】:
我正在尝试使用参数包和一些标准匹配规则编写一个接受另一个函数的函数。举个例子:
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)。 -尾注]
fn 的 std::list<TListElems>... 位似乎会违反此说明,但这并不完全清楚。
问题是:谁是对的? GCC、Clang 还是其他?
【问题讨论】:
标签: c++ c++11 templates language-lawyer variadic-templates